Skip to content

Commit 9ebe6e2

Browse files
authored
Revert "[ClangRepl] Type Directed Code Completion" (#73259)
Reverts #67349 There are some issues with the sanitizers. We will reland once that's fixed.
1 parent aea7929 commit 9ebe6e2

File tree

6 files changed

+51
-444
lines changed

6 files changed

+51
-444
lines changed

clang/include/clang/Interpreter/CodeCompletion.h

+3-22
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,8 @@ namespace clang {
2323
class CodeCompletionResult;
2424
class CompilerInstance;
2525

26-
struct ReplCodeCompleter {
27-
ReplCodeCompleter() = default;
28-
std::string Prefix;
29-
30-
/// \param InterpCI [in] The compiler instance that is used to trigger code
31-
/// completion
32-
33-
/// \param Content [in] The string where code completion is triggered.
34-
35-
/// \param Line [in] The line number of the code completion point.
36-
37-
/// \param Col [in] The column number of the code completion point.
38-
39-
/// \param ParentCI [in] The running interpreter compiler instance that
40-
/// provides ASTContexts.
41-
42-
/// \param CCResults [out] The completion results.
43-
void codeComplete(CompilerInstance *InterpCI, llvm::StringRef Content,
44-
unsigned Line, unsigned Col,
45-
const CompilerInstance *ParentCI,
46-
std::vector<std::string> &CCResults);
47-
};
26+
void codeComplete(CompilerInstance *InterpCI, llvm::StringRef Content,
27+
unsigned Line, unsigned Col, const CompilerInstance *ParentCI,
28+
std::vector<std::string> &CCResults);
4829
} // namespace clang
4930
#endif

clang/include/clang/Interpreter/Interpreter.h

-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ class Interpreter {
101101
const ASTContext &getASTContext() const;
102102
ASTContext &getASTContext();
103103
const CompilerInstance *getCompilerInstance() const;
104-
CompilerInstance *getCompilerInstance();
105104
llvm::Expected<llvm::orc::LLJIT &> getExecutionEngine();
106105

107106
llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code);

clang/lib/Interpreter/CodeCompletion.cpp

+23-199
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
#include "clang/Interpreter/CodeCompletion.h"
1414
#include "clang/AST/ASTImporter.h"
15-
#include "clang/AST/DeclLookups.h"
1615
#include "clang/AST/DeclarationName.h"
1716
#include "clang/AST/ExternalASTSource.h"
1817
#include "clang/Basic/IdentifierTable.h"
@@ -24,8 +23,6 @@
2423
#include "clang/Sema/CodeCompleteConsumer.h"
2524
#include "clang/Sema/CodeCompleteOptions.h"
2625
#include "clang/Sema/Sema.h"
27-
#include "llvm/Support/Debug.h"
28-
#define DEBUG_TYPE "REPLCC"
2926

3027
namespace clang {
3128

@@ -42,15 +39,11 @@ clang::CodeCompleteOptions getClangCompleteOpts() {
4239

4340
class ReplCompletionConsumer : public CodeCompleteConsumer {
4441
public:
45-
ReplCompletionConsumer(std::vector<std::string> &Results,
46-
ReplCodeCompleter &CC)
42+
ReplCompletionConsumer(std::vector<std::string> &Results)
4743
: CodeCompleteConsumer(getClangCompleteOpts()),
4844
CCAllocator(std::make_shared<GlobalCodeCompletionAllocator>()),
49-
CCTUInfo(CCAllocator), Results(Results), CC(CC) {}
45+
CCTUInfo(CCAllocator), Results(Results){};
5046

51-
// The entry of handling code completion. When the function is called, we
52-
// create a `Context`-based handler (see classes defined below) to handle each
53-
// completion result.
5447
void ProcessCodeCompleteResults(class Sema &S, CodeCompletionContext Context,
5548
CodeCompletionResult *InResults,
5649
unsigned NumResults) final;
@@ -63,146 +56,26 @@ class ReplCompletionConsumer : public CodeCompleteConsumer {
6356
std::shared_ptr<GlobalCodeCompletionAllocator> CCAllocator;
6457
CodeCompletionTUInfo CCTUInfo;
6558
std::vector<std::string> &Results;
66-
ReplCodeCompleter &CC;
67-
};
68-
69-
/// The class CompletionContextHandler contains four interfaces, each of
70-
/// which handles one type of completion result.
71-
/// Its derived classes are used to create concrete handlers based on
72-
/// \c CodeCompletionContext.
73-
class CompletionContextHandler {
74-
protected:
75-
CodeCompletionContext CCC;
76-
std::vector<std::string> &Results;
77-
78-
private:
79-
Sema &S;
80-
81-
public:
82-
CompletionContextHandler(Sema &S, CodeCompletionContext CCC,
83-
std::vector<std::string> &Results)
84-
: CCC(CCC), Results(Results), S(S) {}
85-
86-
/// Converts a Declaration completion result to a completion string, and then
87-
/// stores it in Results.
88-
virtual void handleDeclaration(const CodeCompletionResult &Result) {
89-
auto PreferredType = CCC.getPreferredType();
90-
if (PreferredType.isNull()) {
91-
Results.push_back(Result.Declaration->getName().str());
92-
return;
93-
}
94-
95-
if (auto *VD = dyn_cast<VarDecl>(Result.Declaration)) {
96-
auto ArgumentType = VD->getType();
97-
if (PreferredType->isReferenceType()) {
98-
QualType RT = PreferredType->castAs<ReferenceType>()->getPointeeType();
99-
Sema::ReferenceConversions RefConv;
100-
Sema::ReferenceCompareResult RefRelationship =
101-
S.CompareReferenceRelationship(SourceLocation(), RT, ArgumentType,
102-
&RefConv);
103-
switch (RefRelationship) {
104-
case Sema::Ref_Compatible:
105-
case Sema::Ref_Related:
106-
Results.push_back(VD->getName().str());
107-
break;
108-
case Sema::Ref_Incompatible:
109-
break;
110-
}
111-
} else if (S.Context.hasSameType(ArgumentType, PreferredType)) {
112-
Results.push_back(VD->getName().str());
113-
}
114-
}
115-
}
116-
117-
/// Converts a Keyword completion result to a completion string, and then
118-
/// stores it in Results.
119-
virtual void handleKeyword(const CodeCompletionResult &Result) {
120-
auto Prefix = S.getPreprocessor().getCodeCompletionFilter();
121-
// Add keyword to the completion results only if we are in a type-aware
122-
// situation.
123-
if (!CCC.getBaseType().isNull() || !CCC.getPreferredType().isNull())
124-
return;
125-
if (StringRef(Result.Keyword).startswith(Prefix))
126-
Results.push_back(Result.Keyword);
127-
}
128-
129-
/// Converts a Pattern completion result to a completion string, and then
130-
/// stores it in Results.
131-
virtual void handlePattern(const CodeCompletionResult &Result) {}
132-
133-
/// Converts a Macro completion result to a completion string, and then stores
134-
/// it in Results.
135-
virtual void handleMacro(const CodeCompletionResult &Result) {}
136-
};
137-
138-
class DotMemberAccessHandler : public CompletionContextHandler {
139-
public:
140-
DotMemberAccessHandler(Sema &S, CodeCompletionContext CCC,
141-
std::vector<std::string> &Results)
142-
: CompletionContextHandler(S, CCC, Results) {}
143-
void handleDeclaration(const CodeCompletionResult &Result) override {
144-
auto *ID = Result.Declaration->getIdentifier();
145-
if (!ID)
146-
return;
147-
if (!isa<CXXMethodDecl>(Result.Declaration))
148-
return;
149-
const auto *Fun = cast<CXXMethodDecl>(Result.Declaration);
150-
if (Fun->getParent()->getCanonicalDecl() ==
151-
CCC.getBaseType()->getAsCXXRecordDecl()->getCanonicalDecl()) {
152-
LLVM_DEBUG(llvm::dbgs() << "[In HandleCodeCompleteDOT] Name : "
153-
<< ID->getName() << "\n");
154-
Results.push_back(ID->getName().str());
155-
}
156-
}
157-
158-
void handleKeyword(const CodeCompletionResult &Result) override {}
15959
};
16060

16161
void ReplCompletionConsumer::ProcessCodeCompleteResults(
16262
class Sema &S, CodeCompletionContext Context,
16363
CodeCompletionResult *InResults, unsigned NumResults) {
164-
165-
auto Prefix = S.getPreprocessor().getCodeCompletionFilter();
166-
CC.Prefix = Prefix;
167-
168-
std::unique_ptr<CompletionContextHandler> CCH;
169-
170-
// initialize fine-grained code completion handler based on the code
171-
// completion context.
172-
switch (Context.getKind()) {
173-
case CodeCompletionContext::CCC_DotMemberAccess:
174-
CCH.reset(new DotMemberAccessHandler(S, Context, this->Results));
175-
break;
176-
default:
177-
CCH.reset(new CompletionContextHandler(S, Context, this->Results));
178-
};
179-
180-
for (unsigned I = 0; I < NumResults; I++) {
64+
for (unsigned I = 0; I < NumResults; ++I) {
18165
auto &Result = InResults[I];
18266
switch (Result.Kind) {
18367
case CodeCompletionResult::RK_Declaration:
184-
if (Result.Hidden) {
185-
break;
186-
}
187-
if (!Result.Declaration->getDeclName().isIdentifier() ||
188-
!Result.Declaration->getName().startswith(Prefix)) {
189-
break;
68+
if (auto *ID = Result.Declaration->getIdentifier()) {
69+
Results.push_back(ID->getName().str());
19070
}
191-
CCH->handleDeclaration(Result);
19271
break;
19372
case CodeCompletionResult::RK_Keyword:
194-
CCH->handleKeyword(Result);
195-
break;
196-
case CodeCompletionResult::RK_Macro:
197-
CCH->handleMacro(Result);
73+
Results.push_back(Result.Keyword);
19874
break;
199-
case CodeCompletionResult::RK_Pattern:
200-
CCH->handlePattern(Result);
75+
default:
20176
break;
20277
}
20378
}
204-
205-
std::sort(Results.begin(), Results.end());
20679
}
20780

20881
class IncrementalSyntaxOnlyAction : public SyntaxOnlyAction {
@@ -245,16 +118,6 @@ void IncrementalSyntaxOnlyAction::ExecuteAction() {
245118
CI.getASTContext().getTranslationUnitDecl()->setHasExternalVisibleStorage(
246119
true);
247120

248-
// Load all external decls into current context. Under the hood, it calls
249-
// ExternalSource::completeVisibleDeclsMap, which make all decls on the redecl
250-
// chain visible.
251-
//
252-
// This is crucial to code completion on dot members, since a bound variable
253-
// before "." would be otherwise treated out-of-scope.
254-
//
255-
// clang-repl> Foo f1;
256-
// clang-repl> f1.<tab>
257-
CI.getASTContext().getTranslationUnitDecl()->lookups();
258121
SyntaxOnlyAction::ExecuteAction();
259122
}
260123

@@ -271,7 +134,6 @@ ExternalSource::ExternalSource(ASTContext &ChildASTCtxt, FileManager &ChildFM,
271134

272135
bool ExternalSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
273136
DeclarationName Name) {
274-
275137
IdentifierTable &ParentIdTable = ParentASTCtxt.Idents;
276138

277139
auto ParentDeclName =
@@ -297,67 +159,29 @@ void ExternalSource::completeVisibleDeclsMap(
297159
for (auto *DeclCtxt = ParentTUDeclCtxt; DeclCtxt != nullptr;
298160
DeclCtxt = DeclCtxt->getPreviousDecl()) {
299161
for (auto &IDeclContext : DeclCtxt->decls()) {
300-
if (!llvm::isa<NamedDecl>(IDeclContext))
301-
continue;
302-
303-
NamedDecl *Decl = llvm::cast<NamedDecl>(IDeclContext);
304-
305-
auto DeclOrErr = Importer->Import(Decl);
306-
if (!DeclOrErr) {
307-
// if an error happens, it usually means the decl has already been
308-
// imported or the decl is a result of a failed import. But in our
309-
// case, every import is fresh each time code completion is
310-
// triggered. So Import usually doesn't fail. If it does, it just means
311-
// the related decl can't be used in code completion and we can safely
312-
// drop it.
313-
llvm::consumeError(DeclOrErr.takeError());
314-
continue;
315-
}
316-
317-
if (!llvm::isa<NamedDecl>(*DeclOrErr))
318-
continue;
319-
320-
NamedDecl *importedNamedDecl = llvm::cast<NamedDecl>(*DeclOrErr);
321-
322-
SetExternalVisibleDeclsForName(ChildDeclContext,
323-
importedNamedDecl->getDeclName(),
324-
importedNamedDecl);
325-
326-
if (!llvm::isa<CXXRecordDecl>(importedNamedDecl))
327-
continue;
328-
329-
auto *Record = llvm::cast<CXXRecordDecl>(importedNamedDecl);
330-
331-
if (auto Err = Importer->ImportDefinition(Decl)) {
332-
// the same as above
333-
consumeError(std::move(Err));
334-
continue;
162+
if (NamedDecl *Decl = llvm::dyn_cast<NamedDecl>(IDeclContext)) {
163+
if (auto DeclOrErr = Importer->Import(Decl)) {
164+
if (NamedDecl *importedNamedDecl =
165+
llvm::dyn_cast<NamedDecl>(*DeclOrErr)) {
166+
SetExternalVisibleDeclsForName(ChildDeclContext,
167+
importedNamedDecl->getDeclName(),
168+
importedNamedDecl);
169+
}
170+
171+
} else {
172+
llvm::consumeError(DeclOrErr.takeError());
173+
}
335174
}
336-
337-
Record->setHasLoadedFieldsFromExternalStorage(true);
338-
LLVM_DEBUG(llvm::dbgs()
339-
<< "\nCXXRecrod : " << Record->getName() << " size(methods): "
340-
<< std::distance(Record->method_begin(), Record->method_end())
341-
<< " has def?: " << Record->hasDefinition()
342-
<< " # (methods): "
343-
<< std::distance(Record->getDefinition()->method_begin(),
344-
Record->getDefinition()->method_end())
345-
<< "\n");
346-
for (auto *Meth : Record->methods())
347-
SetExternalVisibleDeclsForName(ChildDeclContext, Meth->getDeclName(),
348-
Meth);
349175
}
350176
ChildDeclContext->setHasExternalLexicalStorage(false);
351177
}
352178
}
353179

354-
void ReplCodeCompleter::codeComplete(CompilerInstance *InterpCI,
355-
llvm::StringRef Content, unsigned Line,
356-
unsigned Col,
357-
const CompilerInstance *ParentCI,
358-
std::vector<std::string> &CCResults) {
180+
void codeComplete(CompilerInstance *InterpCI, llvm::StringRef Content,
181+
unsigned Line, unsigned Col, const CompilerInstance *ParentCI,
182+
std::vector<std::string> &CCResults) {
359183
auto DiagOpts = DiagnosticOptions();
360-
auto consumer = ReplCompletionConsumer(CCResults, *this);
184+
auto consumer = ReplCompletionConsumer(CCResults);
361185

362186
auto diag = InterpCI->getDiagnosticsPtr();
363187
std::unique_ptr<ASTUnit> AU(ASTUnit::LoadFromCompilerInvocationAction(

clang/lib/Interpreter/Interpreter.cpp

-4
Original file line numberDiff line numberDiff line change
@@ -319,10 +319,6 @@ const CompilerInstance *Interpreter::getCompilerInstance() const {
319319
return IncrParser->getCI();
320320
}
321321

322-
CompilerInstance *Interpreter::getCompilerInstance() {
323-
return IncrParser->getCI();
324-
}
325-
326322
llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() {
327323
if (!IncrExecutor) {
328324
if (auto Err = CreateExecutor())

clang/tools/clang-repl/ClangRepl.cpp

+15-9
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
#include "clang/Frontend/FrontendDiagnostic.h"
1616
#include "clang/Interpreter/CodeCompletion.h"
1717
#include "clang/Interpreter/Interpreter.h"
18-
#include "clang/Lex/Preprocessor.h"
19-
#include "clang/Sema/Sema.h"
2018

2119
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
2220
#include "llvm/LineEditor/LineEditor.h"
@@ -125,14 +123,22 @@ ReplListCompleter::operator()(llvm::StringRef Buffer, size_t Pos,
125123

126124
return {};
127125
}
128-
auto *MainCI = (*Interp)->getCompilerInstance();
129-
auto CC = clang::ReplCodeCompleter();
130-
CC.codeComplete(MainCI, Buffer, Lines, Pos + 1,
131-
MainInterp.getCompilerInstance(), Results);
126+
127+
codeComplete(
128+
const_cast<clang::CompilerInstance *>((*Interp)->getCompilerInstance()),
129+
Buffer, Lines, Pos + 1, MainInterp.getCompilerInstance(), Results);
130+
131+
size_t space_pos = Buffer.rfind(" ");
132+
llvm::StringRef Prefix;
133+
if (space_pos == llvm::StringRef::npos) {
134+
Prefix = Buffer;
135+
} else {
136+
Prefix = Buffer.substr(space_pos + 1);
137+
}
138+
132139
for (auto c : Results) {
133-
if (c.find(CC.Prefix) == 0)
134-
Comps.push_back(
135-
llvm::LineEditor::Completion(c.substr(CC.Prefix.size()), c));
140+
if (c.find(Prefix) == 0)
141+
Comps.push_back(llvm::LineEditor::Completion(c.substr(Prefix.size()), c));
136142
}
137143
return Comps;
138144
}

0 commit comments

Comments
 (0)