Introduce basic code-completion support for preprocessor directives,
e.g., after a "#" we'll suggest #if, #ifdef, etc.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111943 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index 9a96934..3a77bbb 100644
--- a/lib/Lex/Lexer.cpp
+++ b/lib/Lex/Lexer.cpp
@@ -1523,6 +1523,22 @@
/// This returns true if Result contains a token, false if PP.Lex should be
/// called again.
bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
+ // Check if we are performing code completion.
+ if (PP && PP->isCodeCompletionFile(FileLoc)) {
+ // We're at the end of the file, but we've been asked to consider the
+ // end of the file to be a code-completion token. Return the
+ // code-completion token.
+ Result.startToken();
+ FormTokenWithChars(Result, CurPtr, tok::code_completion);
+
+ // Only do the eof -> code_completion translation once.
+ PP->SetCodeCompletionPoint(0, 0, 0);
+
+ // Silence any diagnostics that occur once we hit the code-completion point.
+ PP->getDiagnostics().setSuppressAllDiagnostics(true);
+ return true;
+ }
+
// If we hit the end of the file while parsing a preprocessor directive,
// end the preprocessor directive first. The next token returned will
// then be the end of file.
@@ -1545,25 +1561,9 @@
FormTokenWithChars(Result, BufferEnd, tok::eof);
return true;
}
-
- // Otherwise, check if we are code-completing, then issue diagnostics for
- // unterminated #if and missing newline.
-
- if (PP && PP->isCodeCompletionFile(FileLoc)) {
- // We're at the end of the file, but we've been asked to consider the
- // end of the file to be a code-completion token. Return the
- // code-completion token.
- Result.startToken();
- FormTokenWithChars(Result, CurPtr, tok::code_completion);
-
- // Only do the eof -> code_completion translation once.
- PP->SetCodeCompletionPoint(0, 0, 0);
-
- // Silence any diagnostics that occur once we hit the code-completion point.
- PP->getDiagnostics().setSuppressAllDiagnostics(true);
- return true;
- }
+ // Issue diagnostics for unterminated #if and missing newline.
+
// If we are in a #if directive, emit an error.
while (!ConditionalStack.empty()) {
if (!PP->isCodeCompletionFile(FileLoc))
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index e000c54..e0729f1 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -16,6 +16,7 @@
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/APInt.h"
@@ -177,6 +178,12 @@
while (1) {
CurLexer->Lex(Tok);
+ if (Tok.is(tok::code_completion)) {
+ if (CodeComplete)
+ CodeComplete->CodeCompleteInConditionalExclusion();
+ continue;
+ }
+
// If this is the end of the buffer, we have an error.
if (Tok.is(tok::eof)) {
// Emit errors for each unterminated conditional on the stack, including
@@ -522,7 +529,11 @@
// Handle stuff like "# /*foo*/ define X" in -E -C mode.
LexUnexpandedToken(Result);
goto TryAgain;
-
+ case tok::code_completion:
+ if (CodeComplete)
+ CodeComplete->CodeCompleteDirective(
+ CurPPLexer->getConditionalStackDepth() > 0);
+ return;
case tok::numeric_constant: // # 7 GNU line marker directive.
if (getLangOptions().AsmPreprocessor)
break; // # 4 is not a preprocessor directive in .S files.
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index d3959aa..04de68b 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -34,6 +34,7 @@
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/ScratchBuffer.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -53,9 +54,9 @@
bool OwnsHeaders)
: Diags(&diags), Features(opts), Target(target),FileMgr(Headers.getFileMgr()),
SourceMgr(SM), HeaderInfo(Headers), ExternalSource(0),
- Identifiers(opts, IILookup), BuiltinInfo(Target), CodeCompletionFile(0),
- SkipMainFilePreamble(0, true), CurPPLexer(0), CurDirLookup(0), Callbacks(0),
- MacroArgCache(0), Record(0) {
+ Identifiers(opts, IILookup), BuiltinInfo(Target), CodeComplete(0),
+ CodeCompletionFile(0), SkipMainFilePreamble(0, true), CurPPLexer(0),
+ CurDirLookup(0), Callbacks(0), MacroArgCache(0), Record(0) {
ScratchBuf = new ScratchBuffer(SourceMgr);
CounterValue = 0; // __COUNTER__ starts at 0.
OwnsHeaderSearch = OwnsHeaders;
@@ -646,6 +647,8 @@
CommentHandler::~CommentHandler() { }
+CodeCompletionHandler::~CodeCompletionHandler() { }
+
void Preprocessor::createPreprocessingRecord() {
if (Record)
return;