/// \name Code-completion callbacks
//@{
/// \brief Process the finalized code-completion results.
- virtual void ProcessCodeCompleteResults(Result *Results,
+ virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
unsigned NumResults) { }
-
- /// \brief Process the set of overload candidates.
+
+ /// \param S the semantic-analyzer object for which code-completion is being
+ /// done.
///
/// \param CurrentArg the index of the current argument.
///
/// \param Candidates an array of overload candidates.
///
/// \param NumCandidates the number of overload candidates
- virtual void ProcessOverloadCandidates(unsigned CurrentArg,
+ virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates) { }
//@}
/// \brief A simple code-completion consumer that prints the results it
/// receives in a simple format.
class PrintingCodeCompleteConsumer : public CodeCompleteConsumer {
- /// \brief The semantic-analysis object to which this code-completion
- /// consumer is attached.
- Sema &SemaRef;
-
/// \brief The raw output stream.
llvm::raw_ostream &OS;
public:
/// \brief Create a new printing code-completion consumer that prints its
/// results to the given raw output stream.
- PrintingCodeCompleteConsumer(Sema &S, bool IncludeMacros,
+ PrintingCodeCompleteConsumer(bool IncludeMacros,
llvm::raw_ostream &OS)
- : CodeCompleteConsumer(IncludeMacros), SemaRef(S), OS(OS) { }
+ : CodeCompleteConsumer(IncludeMacros), OS(OS) { }
/// \brief Prints the finalized code-completion results.
- virtual void ProcessCodeCompleteResults(Result *Results,
+ virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
unsigned NumResults);
- virtual void ProcessOverloadCandidates(unsigned CurrentArg,
+ virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates);
};
/// \brief A code-completion consumer that prints the results it receives
/// in a format that is parsable by the CIndex library.
class CIndexCodeCompleteConsumer : public CodeCompleteConsumer {
- /// \brief The semantic-analysis object to which this code-completion
- /// consumer is attached.
- Sema &SemaRef;
-
/// \brief The raw output stream.
llvm::raw_ostream &OS;
/// \brief Create a new CIndex code-completion consumer that prints its
/// results to the given raw output stream in a format readable to the CIndex
/// library.
- CIndexCodeCompleteConsumer(Sema &S, bool IncludeMacros, llvm::raw_ostream &OS)
- : CodeCompleteConsumer(IncludeMacros), SemaRef(S), OS(OS) { }
+ CIndexCodeCompleteConsumer(bool IncludeMacros, llvm::raw_ostream &OS)
+ : CodeCompleteConsumer(IncludeMacros), OS(OS) { }
/// \brief Prints the finalized code-completion results.
- virtual void ProcessCodeCompleteResults(Result *Results,
+ virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
unsigned NumResults);
- virtual void ProcessOverloadCandidates(unsigned CurrentArg,
+ virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates);
};
class ASTContext;
class CodeCompleteConsumer;
class Sema;
-
+
/// \brief Parse the entire file specified, notifying the ASTConsumer as
/// the file is parsed.
///
/// \param CompleteTranslationUnit When true, the parsed file is
/// considered to be a complete translation unit, and any
/// end-of-translation-unit wrapup will be performed.
+ ///
+ /// \param CompletionConsumer If given, an object to consume code completion
+ /// results.
void ParseAST(Preprocessor &pp, ASTConsumer *C,
ASTContext &Ctx, bool PrintStats = false,
bool CompleteTranslationUnit = true,
- CodeCompleteConsumer *(*CreateCodeCompleter)(Sema &, void *Data) = 0,
- void *CreateCodeCompleterData = 0);
+ CodeCompleteConsumer *CompletionConsumer = 0);
} // end namespace clang
CodeCompleteConsumer::~CodeCompleteConsumer() { }
void
-PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results,
+PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
+ Result *Results,
unsigned NumResults) {
// Print the results.
for (unsigned I = 0; I != NumResults; ++I) {
}
void
-PrintingCodeCompleteConsumer::ProcessOverloadCandidates(unsigned CurrentArg,
+PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
+ unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates) {
for (unsigned I = 0; I != NumCandidates; ++I) {
}
void
-CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results,
+CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
+ Result *Results,
unsigned NumResults) {
// Print the results.
for (unsigned I = 0; I != NumResults; ++I) {
}
void
-CIndexCodeCompleteConsumer::ProcessOverloadCandidates(unsigned CurrentArg,
+CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
+ unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates) {
for (unsigned I = 0; I != NumCandidates; ++I) {
void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
ASTContext &Ctx, bool PrintStats,
bool CompleteTranslationUnit,
- CodeCompleteConsumer *(*CreateCodeCompleter)(Sema &, void *Data),
- void *CreateCodeCompleterData) {
+ CodeCompleteConsumer *CompletionConsumer) {
// Collect global stats on Decls/Stmts (until we have a module streamer).
if (PrintStats) {
Decl::CollectingStats(true);
Stmt::CollectingStats(true);
}
- Sema S(PP, Ctx, *Consumer, CompleteTranslationUnit);
+ Sema S(PP, Ctx, *Consumer, CompleteTranslationUnit, CompletionConsumer);
Parser P(PP, S);
PP.EnterMainSourceFile();
External->StartTranslationUnit(Consumer);
}
- CodeCompleteConsumer *CodeCompleter = 0;
- if (CreateCodeCompleter) {
- CodeCompleter = CreateCodeCompleter(S, CreateCodeCompleterData);
- S.setCodeCompleteConsumer(CodeCompleter);
- }
-
Parser::DeclGroupPtrTy ADecl;
while (!P.ParseTopLevelDecl(ADecl)) { // Not end of file.
Consumer->HandleTranslationUnit(Ctx);
- if (CreateCodeCompleter)
- delete CodeCompleter;
-
if (PrintStats) {
fprintf(stderr, "\nSTATISTICS:\n");
P.getActions().PrintStats();
}
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
- bool CompleteTranslationUnit)
+ bool CompleteTranslationUnit,
+ CodeCompleteConsumer *CodeCompleter)
: LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
- ExternalSource(0), CodeCompleter(0), CurContext(0),
+ ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0),
PreDeclaratorDC(0), CurBlock(0), PackContext(0), ParsingDeclDepth(0),
IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
GlobalNewDeleteDeclared(false), ExprEvalContext(PotentiallyEvaluated),
bool isSelfExpr(Expr *RExpr);
public:
Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
- bool CompleteTranslationUnit = true);
+ bool CompleteTranslationUnit = true,
+ CodeCompleteConsumer *CompletionConsumer = 0);
~Sema() {
if (PackContext) FreePackedContext();
}
/// \name Code completion
//@{
- void setCodeCompleteConsumer(CodeCompleteConsumer *CCC);
virtual void CodeCompleteOrdinaryName(Scope *S);
virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base,
SourceLocation OpLoc,
using namespace clang;
-/// \brief Set the code-completion consumer for semantic analysis.
-void Sema::setCodeCompleteConsumer(CodeCompleteConsumer *CCC) {
- assert(((CodeCompleter != 0) != (CCC != 0)) &&
- "Already set or cleared a code-completion consumer?");
- CodeCompleter = CCC;
-}
-
namespace {
/// \brief A container of code-completion results.
class ResultBuilder {
Results.ExitScope();
}
-static void HandleCodeCompleteResults(CodeCompleteConsumer *CodeCompleter,
- CodeCompleteConsumer::Result *Results,
- unsigned NumResults) {
+static void HandleCodeCompleteResults(Sema *S,
+ CodeCompleteConsumer *CodeCompleter,
+ CodeCompleteConsumer::Result *Results,
+ unsigned NumResults) {
// Sort the results by rank/kind/etc.
std::stable_sort(Results, Results + NumResults, SortCodeCompleteResult());
if (CodeCompleter)
- CodeCompleter->ProcessCodeCompleteResults(Results, NumResults);
+ CodeCompleter->ProcessCodeCompleteResults(*S, Results, NumResults);
}
void Sema::CodeCompleteOrdinaryName(Scope *S) {
0, CurContext, Results);
if (CodeCompleter->includeMacros())
AddMacroResults(PP, NextRank, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
ResultBuilder Results(*this, &ResultBuilder::IsMember);
unsigned NextRank = 0;
-
- if (const RecordType *Record = BaseType->getAs<RecordType>()) {
- NextRank = CollectMemberLookupResults(Record->getDecl(), NextRank,
- Record->getDecl(), Results);
-
- if (getLangOptions().CPlusPlus) {
- if (!Results.empty()) {
- // The "template" keyword can follow "->" or "." in the grammar.
- // However, we only want to suggest the template keyword if something
- // is dependent.
- bool IsDependent = BaseType->isDependentType();
- if (!IsDependent) {
- for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
- if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
- IsDependent = Ctx->isDependentContext();
- break;
- }
- }
-
- if (IsDependent)
- Results.MaybeAddResult(Result("template", NextRank++));
+
+ // If this isn't a record type, we are done.
+ const RecordType *Record = BaseType->getAs<RecordType>();
+ if (!Record)
+ return;
+
+ NextRank = CollectMemberLookupResults(Record->getDecl(), NextRank,
+ Record->getDecl(), Results);
+
+ if (getLangOptions().CPlusPlus) {
+ if (!Results.empty()) {
+ // The "template" keyword can follow "->" or "." in the grammar.
+ // However, we only want to suggest the template keyword if something
+ // is dependent.
+ bool IsDependent = BaseType->isDependentType();
+ if (!IsDependent) {
+ for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
+ if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
+ IsDependent = Ctx->isDependentContext();
+ break;
+ }
}
-
- // We could have the start of a nested-name-specifier. Add those
- // results as well.
- Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
- CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank,
- CurContext, Results);
+
+ if (IsDependent)
+ Results.MaybeAddResult(Result("template", NextRank++));
}
-
- // Add macros
- if (CodeCompleter->includeMacros())
- AddMacroResults(PP, NextRank, Results);
-
- // Hand off the results found for code completion.
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
-
- // We're done!
- return;
+
+ // We could have the start of a nested-name-specifier. Add those
+ // results as well.
+ Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
+ CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank,
+ CurContext, Results);
}
+
+ // Add macros
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, NextRank, Results);
+
+ // Hand off the results found for code completion.
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
if (CodeCompleter->includeMacros())
AddMacroResults(PP, NextRank, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteCase(Scope *S) {
if (CodeCompleter->includeMacros())
AddMacroResults(PP, 1, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
namespace {
if (Cand->Viable)
Results.push_back(ResultCandidate(Cand->Function));
}
- CodeCompleter->ProcessOverloadCandidates(NumArgs, Results.data(),
+ CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(),
Results.size());
}
if (CodeCompleter->includeMacros())
AddMacroResults(PP, NextRank + 1, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteUsing(Scope *S) {
if (CodeCompleter->includeMacros())
AddMacroResults(PP, NextRank, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteUsingDirective(Scope *S) {
Results.ExitScope();
if (CodeCompleter->includeMacros())
AddMacroResults(PP, NextRank, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteNamespaceDecl(Scope *S) {
if (CodeCompleter->includeMacros())
AddMacroResults(PP, 1, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
0, CurContext, Results);
if (CodeCompleter->includeMacros())
AddMacroResults(PP, NextRank, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteOperatorName(Scope *S) {
if (CodeCompleter->includeMacros())
AddMacroResults(PP, NextRank, Results);
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) {
if (!(Attributes & ObjCDeclSpec::DQ_PR_getter))
Results.MaybeAddResult(CodeCompleteConsumer::Result("getter", 0));
Results.ExitScope();
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteObjCFactoryMethod(Scope *S, IdentifierInfo *FName) {
}
Results.ExitScope();
// This also suppresses remaining diagnostics.
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
void Sema::CodeCompleteObjCInstanceMethod(Scope *S, ExprTy *Receiver) {
}
Results.ExitScope();
// This also suppresses remaining diagnostics.
- HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
return P.str();
}
-/// \brief Buld a new code-completion consumer that prints the results of
-/// code completion to standard output.
-static CodeCompleteConsumer *BuildPrintingCodeCompleter(Sema &S,
- void *UserData) {
- const FrontendOptions &Opts = *(FrontendOptions*)UserData;
- if (Opts.DebugCodeCompletionPrinter)
- return new PrintingCodeCompleteConsumer(S, Opts.ShowMacrosInCodeCompletion,
- llvm::outs());
-
- return new CIndexCodeCompleteConsumer(S, Opts.ShowMacrosInCodeCompletion,
- llvm::outs());
-}
-
//===----------------------------------------------------------------------===//
// Basic Parser driver
//===----------------------------------------------------------------------===//
if (InitializeSourceManager(PP, CI.getFrontendOpts(), InFile))
return;
- CodeCompleteConsumer *(*CreateCodeCompleter)(Sema &, void *) = 0;
- void *CreateCodeCompleterData = (void*) &FEOpts;
-
+ llvm::OwningPtr<CodeCompleteConsumer> CCConsumer;
if (!FEOpts.CodeCompletionAt.FileName.empty()) {
// Tell the source manager to chop off the given file at a specific
// line and column.
FEOpts.CodeCompletionAt.Column);
// Set up the creation routine for code-completion.
- CreateCodeCompleter = BuildPrintingCodeCompleter;
+ if (FEOpts.DebugCodeCompletionPrinter)
+ CCConsumer.reset(
+ new PrintingCodeCompleteConsumer(FEOpts.ShowMacrosInCodeCompletion,
+ llvm::outs()));
+ else
+ CCConsumer.reset(
+ new CIndexCodeCompleteConsumer(FEOpts.ShowMacrosInCodeCompletion,
+ llvm::outs()));
} else {
PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
<< FEOpts.CodeCompletionAt.FileName;
// Run the AST consumer action.
ParseAST(PP, Consumer.get(), CI.getASTContext(), FEOpts.ShowStats,
CompleteTranslationUnit,
- CreateCodeCompleter, CreateCodeCompleterData);
+ CCConsumer.get());
} else {
// Initialize builtin info.
PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),