llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.78k stars 11.9k forks source link

[clang] Introduce `SemaCodeCompletion` #92311

Closed Endilll closed 5 months ago

Endilll commented 5 months ago

This patch continues previous efforts to split Sema up, this time covering code completion. Context can be found in #84184. Dropping Code prefix from function names in SemaCodeCompletion would make sense, but I think this PR has enough changes already. As usual, formatting changes are done as a separate commit. Hopefully this helps with the review.

llvmbot commented 5 months ago

@llvm/pr-subscribers-clang

Author: Vlad Serebrennikov (Endilll)

Changes This patch continues previous efforts to split `Sema` up, this time covering code completion. Context can be found in #84184. Dropping `Code` prefix from function names in `SemaCodeCompletion` would make sense, but I think this PR has enough changes already. As usual, formatting changes are done as a separate commit. Hopefully this helps with the review. --- Patch is 216.36 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/92311.diff 17 Files Affected: - (modified) clang/include/clang/Parse/Parser.h (+3-1) - (modified) clang/include/clang/Sema/Sema.h (+14-211) - (added) clang/include/clang/Sema/SemaCodeCompletion.h (+237) - (modified) clang/lib/Frontend/ASTUnit.cpp (+3-2) - (modified) clang/lib/Parse/ParseDecl.cpp (+34-28) - (modified) clang/lib/Parse/ParseDeclCXX.cpp (+31-26) - (modified) clang/lib/Parse/ParseExpr.cpp (+17-14) - (modified) clang/lib/Parse/ParseExprCXX.cpp (+27-19) - (modified) clang/lib/Parse/ParseInit.cpp (+5-3) - (modified) clang/lib/Parse/ParseObjc.cpp (+81-67) - (modified) clang/lib/Parse/ParseOpenMP.cpp (+7-4) - (modified) clang/lib/Parse/ParsePragma.cpp (+3-1) - (modified) clang/lib/Parse/ParseStmt.cpp (+14-10) - (modified) clang/lib/Parse/ParseTemplate.cpp (+2-2) - (modified) clang/lib/Parse/Parser.cpp (+26-21) - (modified) clang/lib/Sema/Sema.cpp (+4-2) - (modified) clang/lib/Sema/SemaCodeComplete.cpp (+695-611) ``````````diff diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 7a8c2bcde804e..cefeba90b2c92 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -18,6 +18,7 @@ #include "clang/Lex/CodeCompletionHandler.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/SemaCodeCompletion.h" #include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" #include "llvm/ADT/SmallVector.h" @@ -2998,7 +2999,8 @@ class Parser : public CodeCompletionHandler { IdentifierInfo *TryParseCXX11AttributeIdentifier( SourceLocation &Loc, - Sema::AttributeCompletion Completion = Sema::AttributeCompletion::None, + SemaCodeCompletion::AttributeCompletion Completion = + SemaCodeCompletion::AttributeCompletion::None, const IdentifierInfo *EnclosingScope = nullptr); void MaybeParseHLSLAnnotations(Declarator &D, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6a414aa57f32b..8b35959a6285b 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -167,6 +167,7 @@ class Preprocessor; class PseudoDestructorTypeStorage; class PseudoObjectExpr; class QualType; +class SemaCodeCompletion; class SemaCUDA; class SemaHLSL; class SemaObjC; @@ -481,9 +482,8 @@ class Sema final : public SemaBase { // 29. C++ Variadic Templates (SemaTemplateVariadic.cpp) // 30. Constraints and Concepts (SemaConcept.cpp) // 31. Types (SemaType.cpp) - // 32. Code Completion (SemaCodeComplete.cpp) - // 33. FixIt Helpers (SemaFixItUtils.cpp) - // 34. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp) + // 32. FixIt Helpers (SemaFixItUtils.cpp) + // 33. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp) /// \name Semantic Analysis /// Implementations are in Sema.cpp @@ -984,6 +984,11 @@ class Sema final : public SemaBase { /// CurContext - This is the current declaration context of parsing. DeclContext *CurContext; + SemaCodeCompletion &CodeCompletion() { + assert(CodeCompletionPtr); + return *CodeCompletionPtr; + } + SemaCUDA &CUDA() { assert(CUDAPtr); return *CUDAPtr; @@ -1044,6 +1049,7 @@ class Sema final : public SemaBase { mutable IdentifierInfo *Ident_super; + std::unique_ptr CodeCompletionPtr; std::unique_ptr CUDAPtr; std::unique_ptr HLSLPtr; std::unique_ptr ObjCPtr; @@ -4799,6 +4805,11 @@ class Sema final : public SemaBase { DelayedDiagnostics.popUndelayed(state); } + ValueDecl *tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl, + CXXScopeSpec &SS, + ParsedType TemplateTypeTy, + IdentifierInfo *MemberOrBase); + private: void setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem, QualType ResultTy, @@ -4809,11 +4820,6 @@ class Sema final : public SemaBase { // of a ComparisonCategoryType enumerator. llvm::SmallBitVector FullyCheckedComparisonCategories; - ValueDecl *tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl, - CXXScopeSpec &SS, - ParsedType TemplateTypeTy, - IdentifierInfo *MemberOrBase); - /// Check if there is a field shadowing. void CheckShadowInheritedFields(const SourceLocation &Loc, DeclarationName FieldName, @@ -11651,209 +11657,6 @@ class Sema final : public SemaBase { // // - /// \name Code Completion - /// Implementations are in SemaCodeComplete.cpp - ///@{ - -public: - /// Code-completion consumer. - CodeCompleteConsumer *CodeCompleter; - - /// Describes the context in which code completion occurs. - enum ParserCompletionContext { - /// Code completion occurs at top-level or namespace context. - PCC_Namespace, - /// Code completion occurs within a class, struct, or union. - PCC_Class, - /// Code completion occurs within an Objective-C interface, protocol, - /// or category. - PCC_ObjCInterface, - /// Code completion occurs within an Objective-C implementation or - /// category implementation - PCC_ObjCImplementation, - /// Code completion occurs within the list of instance variables - /// in an Objective-C interface, protocol, category, or implementation. - PCC_ObjCInstanceVariableList, - /// Code completion occurs following one or more template - /// headers. - PCC_Template, - /// Code completion occurs following one or more template - /// headers within a class. - PCC_MemberTemplate, - /// Code completion occurs within an expression. - PCC_Expression, - /// Code completion occurs within a statement, which may - /// also be an expression or a declaration. - PCC_Statement, - /// Code completion occurs at the beginning of the - /// initialization statement (or expression) in a for loop. - PCC_ForInit, - /// Code completion occurs within the condition of an if, - /// while, switch, or for statement. - PCC_Condition, - /// Code completion occurs within the body of a function on a - /// recovery path, where we do not have a specific handle on our position - /// in the grammar. - PCC_RecoveryInFunction, - /// Code completion occurs where only a type is permitted. - PCC_Type, - /// Code completion occurs in a parenthesized expression, which - /// might also be a type cast. - PCC_ParenthesizedExpression, - /// Code completion occurs within a sequence of declaration - /// specifiers within a function, method, or block. - PCC_LocalDeclarationSpecifiers, - /// Code completion occurs at top-level in a REPL session - PCC_TopLevelOrExpression, - }; - - void CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path); - void CodeCompleteOrdinaryName(Scope *S, - ParserCompletionContext CompletionContext); - void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, bool AllowNonIdentifiers, - bool AllowNestedNameSpecifiers); - - struct CodeCompleteExpressionData; - void CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData &Data); - void CodeCompleteExpression(Scope *S, QualType PreferredType, - bool IsParenthesized = false); - void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, Expr *OtherOpBase, - SourceLocation OpLoc, bool IsArrow, - bool IsBaseExprStatement, - QualType PreferredType); - void CodeCompletePostfixExpression(Scope *S, ExprResult LHS, - QualType PreferredType); - void CodeCompleteTag(Scope *S, unsigned TagSpec); - void CodeCompleteTypeQualifiers(DeclSpec &DS); - void CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D, - const VirtSpecifiers *VS = nullptr); - void CodeCompleteBracketDeclarator(Scope *S); - void CodeCompleteCase(Scope *S); - enum class AttributeCompletion { - Attribute, - Scope, - None, - }; - void CodeCompleteAttribute( - AttributeCommonInfo::Syntax Syntax, - AttributeCompletion Completion = AttributeCompletion::Attribute, - const IdentifierInfo *Scope = nullptr); - /// Determines the preferred type of the current function argument, by - /// examining the signatures of all possible overloads. - /// Returns null if unknown or ambiguous, or if code completion is off. - /// - /// If the code completion point has been reached, also reports the function - /// signatures that were considered. - /// - /// FIXME: rename to GuessCallArgumentType to reduce confusion. - QualType ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args, - SourceLocation OpenParLoc); - QualType ProduceConstructorSignatureHelp(QualType Type, SourceLocation Loc, - ArrayRef Args, - SourceLocation OpenParLoc, - bool Braced); - QualType ProduceCtorInitMemberSignatureHelp( - Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy, - ArrayRef ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc, - bool Braced); - QualType ProduceTemplateArgumentSignatureHelp( - TemplateTy, ArrayRef, SourceLocation LAngleLoc); - void CodeCompleteInitializer(Scope *S, Decl *D); - /// Trigger code completion for a record of \p BaseType. \p InitExprs are - /// expressions in the initializer list seen so far and \p D is the current - /// Designation being parsed. - void CodeCompleteDesignator(const QualType BaseType, - llvm::ArrayRef InitExprs, - const Designation &D); - void CodeCompleteAfterIf(Scope *S, bool IsBracedThen); - - void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext, - bool IsUsingDeclaration, QualType BaseType, - QualType PreferredType); - void CodeCompleteUsing(Scope *S); - void CodeCompleteUsingDirective(Scope *S); - void CodeCompleteNamespaceDecl(Scope *S); - void CodeCompleteNamespaceAliasDecl(Scope *S); - void CodeCompleteOperatorName(Scope *S); - void CodeCompleteConstructorInitializer( - Decl *Constructor, ArrayRef Initializers); - - void CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, - bool AfterAmpersand); - void CodeCompleteAfterFunctionEquals(Declarator &D); - - void CodeCompleteObjCAtDirective(Scope *S); - void CodeCompleteObjCAtVisibility(Scope *S); - void CodeCompleteObjCAtStatement(Scope *S); - void CodeCompleteObjCAtExpression(Scope *S); - void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS); - void CodeCompleteObjCPropertyGetter(Scope *S); - void CodeCompleteObjCPropertySetter(Scope *S); - void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, - bool IsParameter); - void CodeCompleteObjCMessageReceiver(Scope *S); - void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, - ArrayRef SelIdents, - bool AtArgumentExpression); - void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, - ArrayRef SelIdents, - bool AtArgumentExpression, - bool IsSuper = false); - void CodeCompleteObjCInstanceMessage( - Scope *S, Expr *Receiver, ArrayRef SelIdents, - bool AtArgumentExpression, ObjCInterfaceDecl *Super = nullptr); - void CodeCompleteObjCForCollection(Scope *S, DeclGroupPtrTy IterationVar); - void CodeCompleteObjCSelector(Scope *S, - ArrayRef SelIdents); - void - CodeCompleteObjCProtocolReferences(ArrayRef Protocols); - void CodeCompleteObjCProtocolDecl(Scope *S); - void CodeCompleteObjCInterfaceDecl(Scope *S); - void CodeCompleteObjCClassForwardDecl(Scope *S); - void CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, - SourceLocation ClassNameLoc); - void CodeCompleteObjCImplementationDecl(Scope *S); - void CodeCompleteObjCInterfaceCategory(Scope *S, IdentifierInfo *ClassName, - SourceLocation ClassNameLoc); - void CodeCompleteObjCImplementationCategory(Scope *S, - IdentifierInfo *ClassName, - SourceLocation ClassNameLoc); - void CodeCompleteObjCPropertyDefinition(Scope *S); - void CodeCompleteObjCPropertySynthesizeIvar(Scope *S, - IdentifierInfo *PropertyName); - void CodeCompleteObjCMethodDecl(Scope *S, - std::optional IsInstanceMethod, - ParsedType ReturnType); - void CodeCompleteObjCMethodDeclSelector( - Scope *S, bool IsInstanceMethod, bool AtParameterName, - ParsedType ReturnType, ArrayRef SelIdents); - void CodeCompleteObjCClassPropertyRefExpr(Scope *S, - const IdentifierInfo &ClassName, - SourceLocation ClassNameLoc, - bool IsBaseExprStatement); - void CodeCompletePreprocessorDirective(bool InConditional); - void CodeCompleteInPreprocessorConditionalExclusion(Scope *S); - void CodeCompletePreprocessorMacroName(bool IsDefinition); - void CodeCompletePreprocessorExpression(); - void CodeCompletePreprocessorMacroArgument(Scope *S, IdentifierInfo *Macro, - MacroInfo *MacroInfo, - unsigned Argument); - void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled); - void CodeCompleteNaturalLanguage(); - void CodeCompleteAvailabilityPlatformName(); - void - GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo, - SmallVectorImpl &Results); - - ///@} - - // - // - // ------------------------------------------------------------------------- - // - // - /// \name FixIt Helpers /// Implementations are in SemaFixItUtils.cpp ///@{ diff --git a/clang/include/clang/Sema/SemaCodeCompletion.h b/clang/include/clang/Sema/SemaCodeCompletion.h new file mode 100644 index 0000000000000..6bf0f2473cbf4 --- /dev/null +++ b/clang/include/clang/Sema/SemaCodeCompletion.h @@ -0,0 +1,237 @@ +//===----- SemaCodeCompletion.h ------ Code completion support ------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// This file declares facilities that support code completion. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_SEMACODECOMPLETION_H +#define LLVM_CLANG_SEMA_SEMACODECOMPLETION_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Type.h" +#include "clang/Basic/AttributeCommonInfo.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Lex/MacroInfo.h" +#include "clang/Lex/ModuleLoader.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Designator.h" +#include "clang/Sema/Ownership.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/SemaBase.h" +#include "llvm/ADT/StringRef.h" +#include + +namespace clang { + +class SemaCodeCompletion : public SemaBase { +public: + SemaCodeCompletion(Sema &S, CodeCompleteConsumer *CompletionConsumer); + + using TemplateTy = OpaquePtr; + using DeclGroupPtrTy = OpaquePtr; + + /// Code-completion consumer. + CodeCompleteConsumer *CodeCompleter; + + /// Describes the context in which code completion occurs. + enum ParserCompletionContext { + /// Code completion occurs at top-level or namespace context. + PCC_Namespace, + /// Code completion occurs within a class, struct, or union. + PCC_Class, + /// Code completion occurs within an Objective-C interface, protocol, + /// or category. + PCC_ObjCInterface, + /// Code completion occurs within an Objective-C implementation or + /// category implementation + PCC_ObjCImplementation, + /// Code completion occurs within the list of instance variables + /// in an Objective-C interface, protocol, category, or implementation. + PCC_ObjCInstanceVariableList, + /// Code completion occurs following one or more template + /// headers. + PCC_Template, + /// Code completion occurs following one or more template + /// headers within a class. + PCC_MemberTemplate, + /// Code completion occurs within an expression. + PCC_Expression, + /// Code completion occurs within a statement, which may + /// also be an expression or a declaration. + PCC_Statement, + /// Code completion occurs at the beginning of the + /// initialization statement (or expression) in a for loop. + PCC_ForInit, + /// Code completion occurs within the condition of an if, + /// while, switch, or for statement. + PCC_Condition, + /// Code completion occurs within the body of a function on a + /// recovery path, where we do not have a specific handle on our position + /// in the grammar. + PCC_RecoveryInFunction, + /// Code completion occurs where only a type is permitted. + PCC_Type, + /// Code completion occurs in a parenthesized expression, which + /// might also be a type cast. + PCC_ParenthesizedExpression, + /// Code completion occurs within a sequence of declaration + /// specifiers within a function, method, or block. + PCC_LocalDeclarationSpecifiers, + /// Code completion occurs at top-level in a REPL session + PCC_TopLevelOrExpression, + }; + + void CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path); + void CodeCompleteOrdinaryName(Scope *S, + ParserCompletionContext CompletionContext); + void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, bool AllowNonIdentifiers, + bool AllowNestedNameSpecifiers); + + struct CodeCompleteExpressionData; + void CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData &Data); + void CodeCompleteExpression(Scope *S, QualType PreferredType, + bool IsParenthesized = false); + void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, Expr *OtherOpBase, + SourceLocation OpLoc, bool IsArrow, + bool IsBaseExprStatement, + QualType PreferredType); + void CodeCompletePostfixExpression(Scope *S, ExprResult LHS, + QualType PreferredType); + void CodeCompleteTag(Scope *S, unsigned TagSpec); + void CodeCompleteTypeQualifiers(DeclSpec &DS); + void CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D, + const VirtSpecifiers *VS = nullptr); + void CodeCompleteBracketDeclarator(Scope *S); + void CodeCompleteCase(Scope *S); + enum class AttributeCompletion { + Attribute, + Scope, + None, + }; + void CodeCompleteAttribute( + AttributeCommonInfo::Syntax Syntax, + AttributeCompletion Completion = AttributeCompletion::Attribute, + const IdentifierInfo *Scope = nullptr); + /// Determines the preferred type of the current function argument, by + /// examining the signatures of all possible overloads. + /// Returns null if unknown or ambiguous, or if code completion is off. + /// + /// If the code completion point has been reached, also reports the function + /// signatures that were considered. + /// + /// FIXME: rename to GuessCallArgumentType to reduce confusion. + QualType ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args, + SourceLocation OpenParLoc); + QualType ProduceConstructorSignatureHelp(QualType Type, SourceLocation Loc, + ArrayRef Args, + SourceLocation OpenParLoc, + bool Braced); + QualType ProduceCtorInitMemberSignatureHelp( + Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy, + Ar... [truncated] ``````````