diff --git a/include/Basic/Location.h b/include/Basic/Location.h index 7672cc25..d28f6cb9 100644 --- a/include/Basic/Location.h +++ b/include/Basic/Location.h @@ -29,6 +29,12 @@ struct Range { Position end; }; +struct Location { + DocumentUri uri; + + Range range; +}; + struct TextEdit { /// The range of the text document to be manipulated. To insert /// text into a document create a range where start === end. @@ -39,10 +45,4 @@ struct TextEdit { string newText; }; -struct Location { - DocumentUri uri; - - Range range; -}; - } // namespace clice::proto diff --git a/include/Basic/SymbolKind.h b/include/Basic/SymbolKind.h deleted file mode 100644 index 858b44ba..00000000 --- a/include/Basic/SymbolKind.h +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once - -#include "clang/AST/Decl.h" -#include "Support/Support.h" - -namespace clice { - -/// In the LSP, there are several different kinds, such as `SemanticTokenType`, -/// `CompletionItemKind`, and `SymbolKind`. Unfortunately, these kinds do not cover all the semantic -/// information we need. It's also inconsistent that some kinds exist in one category but not in -/// another, for example, `Namespace` is present in `SemanticTokenType` but not in -/// `CompletionItemKind`. To address this, we define our own `SymbolKind`, which will be used -/// consistently across our responses to the client and in the index. Users who prefer to stick to -/// standard LSP kinds can map our `SymbolKind` to the corresponding LSP kinds through -/// configuration. -struct SymbolKind : support::Enum { - enum Kind : uint8_t { - Comment = 0, ///< C/C++ comments. - Number, ///< C/C++ number literal. - Character, ///< C/C++ character literal. - String, ///< C/C++ string literal. - Keyword, ///< C/C++ keyword. - Directive, ///< C/C++ preprocessor directive, e.g. `#include`. - Header, ///< C/C++ header name, e.g. `` and `"foo.h"`. - Module, ///< C++20 module name. - Macro, ///< C/C++ macro. - MacroParameter, ///< C/C++ macro parameter. - Namespace, ///> C++ namespace. - Class, ///> C/C++ class. - Struct, ///> C/C++ struct. - Union, ///> C/C++ union. - Enum, ///> C/C++ enum. - Type, ///> C/C++ type alias and C++ template type parameter. - Field, ///> C/C++ field. - EnumMember, ///> C/C++ enum member. - Function, ///> C/C++ function. - Method, ///> C++ method. - Variable, ///> C/C++ variable, includes C++17 structured bindings. - Parameter, ///> C/C++ parameter. - Label, ///> C/C++ label. - Concept, ///> C++20 concept. - Attribute, ///> GNU/MSVC/C++11/C23 attribute. - Operator, ///> C/C++ operator. - Paren, ///> `(` and `)`. - Bracket, ///> `[` and `]`. - Brace, ///> `{` and `}`. - Angle, ///> `<` and `>`. - Invalid, - }; - - using Enum::Enum; - - constexpr inline static auto InvalidEnum = Kind::Invalid; - - static SymbolKind from(const clang::Decl* decl); - - static SymbolKind from(const clang::tok::TokenKind kind); -}; - -} // namespace clice diff --git a/include/Compiler/Semantic.h b/include/Compiler/Semantic.h index 5d0365d0..8d56f72d 100644 --- a/include/Compiler/Semantic.h +++ b/include/Compiler/Semantic.h @@ -1,46 +1,96 @@ #include "Compiler.h" #include "Resolver.h" - -#include "Support/Enum.h" -#include "Support/FileSystem.h" #include "Utility.h" +#include "Support/Support.h" + namespace clice { -enum class RelationKind : uint32_t { - Invalid, - Declaration, - Definition, - Reference, - // Write Relation. - Read, - Write, - Interface, - Implementation, - /// When target is a type definition of source, source is possible type or constructor. - TypeDefinition, +/// In the LSP, there are several different kinds, such as `SemanticTokenType`, +/// `CompletionItemKind`, and `SymbolKind`. Unfortunately, these kinds do not cover all the semantic +/// information we need. It's also inconsistent that some kinds exist in one category but not in +/// another, for example, `Namespace` is present in `SemanticTokenType` but not in +/// `CompletionItemKind`. To address this, we define our own `SymbolKind`, which will be used +/// consistently across our responses to the client and in the index. Users who prefer to stick to +/// standard LSP kinds can map our `SymbolKind` to the corresponding LSP kinds through +/// configuration. +struct SymbolKind : support::Enum { + enum Kind : uint8_t { + Comment = 0, ///< C/C++ comments. + Number, ///< C/C++ number literal. + Character, ///< C/C++ character literal. + String, ///< C/C++ string literal. + Keyword, ///< C/C++ keyword. + Directive, ///< C/C++ preprocessor directive, e.g. `#include`. + Header, ///< C/C++ header name, e.g. `` and `"foo.h"`. + Module, ///< C++20 module name. + Macro, ///< C/C++ macro. + MacroParameter, ///< C/C++ macro parameter. + Namespace, ///> C++ namespace. + Class, ///> C/C++ class. + Struct, ///> C/C++ struct. + Union, ///> C/C++ union. + Enum, ///> C/C++ enum. + Type, ///> C/C++ type alias and C++ template type parameter. + Field, ///> C/C++ field. + EnumMember, ///> C/C++ enum member. + Function, ///> C/C++ function. + Method, ///> C++ method. + Variable, ///> C/C++ variable, includes C++17 structured bindings. + Parameter, ///> C/C++ parameter. + Label, ///> C/C++ label. + Concept, ///> C++20 concept. + Attribute, ///> GNU/MSVC/C++11/C23 attribute. + Operator, ///> C/C++ operator. + Paren, ///> `(` and `)`. + Bracket, ///> `[` and `]`. + Brace, ///> `{` and `}`. + Angle, ///> `<` and `>`. + Invalid, + }; - /// When target is a base class of source. - Base, - /// When target is a derived class of source. - Derived, + using Enum::Enum; - /// When target is a constructor of source. - Constructor, - /// When target is a destructor of source. - Destructor, + constexpr inline static auto InvalidEnum = Kind::Invalid; - // When target is a caller of source. - Caller, - // When target is a callee of source. - Callee, + static SymbolKind from(const clang::Decl* decl); + + static SymbolKind from(const clang::tok::TokenKind kind); }; -// struct RelationKind : enum_type { -// using enum RelationKinds; -// using enum_type::enum_type; -// using enum_type::operator=; -// }; +/// A bit field enum to describe the kind of relation between two symbols. +struct RelationKind : support::Enum { + enum Kind : uint32_t { + Invalid, + Declaration, + Definition, + Reference, + // Write Relation. + Read, + Write, + Interface, + Implementation, + /// When target is a type definition of source, source is possible type or constructor. + TypeDefinition, + + /// When target is a base class of source. + Base, + /// When target is a derived class of source. + Derived, + + /// When target is a constructor of source. + Constructor, + /// When target is a destructor of source. + Destructor, + + // When target is a caller of source. + Caller, + // When target is a callee of source. + Callee, + }; + + using Enum::Enum; +}; enum class OccurrenceKind { /// This occurrence directly corresponds to a unique source symbol. @@ -53,10 +103,6 @@ enum class OccurrenceKind { Instantiation, }; -enum class SymbolKind { - -}; - template class SemanticVisitor : public clang::RecursiveASTVisitor> { public: @@ -97,7 +143,7 @@ public: /// Always uses spelling location if the original location is a macro location. void handleOccurrence(const clang::Decl* decl, clang::SourceLocation location, - OccurrenceKind kind = OccurrenceKind::Source) {} + RelationKind kind = RelationKind::Invalid) {} /// Builtin type doesn't have corresponding decl. So we handle it separately. /// And it is possible that a builtin type is composed of multiple tokens. @@ -106,12 +152,7 @@ public: clang::SourceRange range, OccurrenceKind kind = OccurrenceKind::Source) {} - void handleOccurrence(clang::Attr* attr, clang::SourceRange range) {} - - /// Always uses expansion location if the original location is a macro location. - void handleRelation(const clang::Decl* decl, RelationKind kind, clang::SourceRange range) { - /// - } + void handleOccurrence(const clang::Attr* attr, clang::SourceRange range) {} public: /// ============================================================================ @@ -136,7 +177,7 @@ public: VISIT_DECL(NamespaceDecl) { /// `namespace Foo { }` /// ^~~~ definition - getDerived().handleOccurrence(decl, decl->getLocation()); + getDerived().handleOccurrence(decl, decl->getLocation(), RelationKind::Definition); return true; } @@ -144,72 +185,80 @@ public: /// `namespace Foo = Bar` /// ^ ^~~~ reference /// ^~~~ definition - getDerived().handleOccurrence(decl, decl->getLocation()); - getDerived().handleOccurrence(decl->getNamespace(), decl->getTargetNameLoc()); + getDerived().handleOccurrence(decl, decl->getLocation(), RelationKind::Definition); + getDerived().handleOccurrence(decl->getNamespace(), + decl->getTargetNameLoc(), + RelationKind::Reference); return true; } VISIT_DECL(UsingDirectiveDecl) { /// `using namespace Foo` /// ^~~~~~~ reference - getDerived().handleOccurrence(decl->getNominatedNamespace(), decl->getLocation()); + getDerived().handleOccurrence(decl->getNominatedNamespace(), + decl->getLocation(), + RelationKind::Reference); return true; } VISIT_DECL(LabelDecl) { /// `label:` /// ^~~~ definition - getDerived().handleOccurrence(decl, decl->getLocation()); + getDerived().handleOccurrence(decl, decl->getLocation(), RelationKind::Definition); return true; } VISIT_DECL(FieldDecl) { /// `int foo;` /// ^~~~ definition - getDerived().handleOccurrence(decl, decl->getLocation()); + getDerived().handleOccurrence(decl, decl->getLocation(), RelationKind::Definition); + /// FIXME: add Type Definition return true; } VISIT_DECL(EnumConstantDecl) { /// `enum Foo { bar };` /// ^~~~ definition - getDerived().handleOccurrence(decl, decl->getLocation()); + getDerived().handleOccurrence(decl, decl->getLocation(), RelationKind::Definition); + /// FIXME: add Type Definition return true; } VISIT_DECL(UsingDecl) { /// `using Foo::bar;` /// ^~~~ reference - getDerived().handleOccurrence(decl, decl->getLocation()); - /// FIXME: + for(auto shadow: decl->shadows()) { + getDerived().handleOccurrence(shadow, decl->getLocation(), RelationKind::Reference); + } return true; } VISIT_DECL(BindingDecl) { /// `auto [a, b] = std::make_tuple(1, 2);` /// ^~~~ definition - getDerived().handleOccurrence(decl, decl->getLocation()); + getDerived().handleOccurrence(decl, decl->getLocation(), RelationKind::Definition); + /// FIXME: add Type Definition return true; } VISIT_DECL(TemplateTypeParmDecl) { /// `template ` /// ^~~~ definition - getDerived().handleOccurrence(decl, decl->getLocation()); + getDerived().handleOccurrence(decl, decl->getLocation(), RelationKind::Definition); return true; } VISIT_DECL(TemplateTemplateParmDecl) { /// `template