зеркало из https://github.com/microsoft/clang-1.git
Introduce a preprocessor code-completion hook for contexts where we
expect "natural" language and should not provide any completions, e.g., comments, string literals, #error. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112054 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
1e32ca6e30
Коммит
55817afdf9
|
@ -55,6 +55,11 @@ public:
|
|||
virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro,
|
||||
MacroInfo *MacroInfo,
|
||||
unsigned ArgumentIndex) { }
|
||||
|
||||
/// \brief Callback invoked when performing code completion in a part of the
|
||||
/// file where we expect natural language, e.g., a comment, string, or
|
||||
/// #error directive.
|
||||
virtual void CodeCompleteNaturalLanguage() { }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -392,6 +392,10 @@ public:
|
|||
CodeComplete = 0;
|
||||
}
|
||||
|
||||
/// \brief Hook used by the lexer to invoke the "natural language" code
|
||||
/// completion point.
|
||||
void CodeCompleteNaturalLanguage();
|
||||
|
||||
/// \brief Retrieve the preprocessing record, or NULL if there is no
|
||||
/// preprocessing record.
|
||||
PreprocessingRecord *getPreprocessingRecord() const { return Record; }
|
||||
|
|
|
@ -1540,6 +1540,7 @@ private:
|
|||
virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro,
|
||||
MacroInfo *MacroInfo,
|
||||
unsigned ArgumentIndex);
|
||||
virtual void CodeCompleteNaturalLanguage();
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
@ -3244,6 +3244,10 @@ public:
|
|||
IdentifierInfo *Macro,
|
||||
MacroInfo *MacroInfo,
|
||||
unsigned Argument) { }
|
||||
|
||||
/// \brief Callback invoked when performing code completion in a context where
|
||||
/// we expect a natural language, e.g., inside a comment or string.
|
||||
virtual void CodeCompleteNaturalLanguage() { }
|
||||
//@}
|
||||
};
|
||||
|
||||
|
|
|
@ -4363,6 +4363,7 @@ public:
|
|||
IdentifierInfo *Macro,
|
||||
MacroInfo *MacroInfo,
|
||||
unsigned Argument);
|
||||
virtual void CodeCompleteNaturalLanguage();
|
||||
void GatherGlobalCodeCompletions(
|
||||
llvm::SmallVectorImpl<CodeCompletionResult> &Results);
|
||||
//@}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "clang/Lex/Lexer.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Lex/LexDiagnostic.h"
|
||||
#include "clang/Lex/CodeCompletionHandler.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
@ -962,8 +963,9 @@ void Lexer::LexStringLiteral(Token &Result, const char *CurPtr, bool Wide) {
|
|||
|
||||
if (C == '\n' || C == '\r' || // Newline.
|
||||
(C == 0 && CurPtr-1 == BufferEnd)) { // End of file.
|
||||
if (!isLexingRawMode() && !Features.AsmPreprocessor &&
|
||||
!PP->isCodeCompletionFile(FileLoc))
|
||||
if (C == 0 && PP && PP->isCodeCompletionFile(FileLoc))
|
||||
PP->CodeCompleteNaturalLanguage();
|
||||
else if (!isLexingRawMode() && !Features.AsmPreprocessor)
|
||||
Diag(BufferPtr, diag::err_unterminated_string);
|
||||
FormTokenWithChars(Result, CurPtr-1, tok::unknown);
|
||||
return;
|
||||
|
@ -1040,8 +1042,9 @@ void Lexer::LexCharConstant(Token &Result, const char *CurPtr) {
|
|||
C = getAndAdvanceChar(CurPtr, Result);
|
||||
} else if (C == '\n' || C == '\r' || // Newline.
|
||||
(C == 0 && CurPtr-1 == BufferEnd)) { // End of file.
|
||||
if (!isLexingRawMode() && !Features.AsmPreprocessor &&
|
||||
!PP->isCodeCompletionFile(FileLoc))
|
||||
if (C == 0 && PP && PP->isCodeCompletionFile(FileLoc))
|
||||
PP->CodeCompleteNaturalLanguage();
|
||||
else if (!isLexingRawMode() && !Features.AsmPreprocessor)
|
||||
Diag(BufferPtr, diag::err_unterminated_char);
|
||||
FormTokenWithChars(Result, CurPtr-1, tok::unknown);
|
||||
return;
|
||||
|
@ -1185,7 +1188,13 @@ bool Lexer::SkipBCPLComment(Token &Result, const char *CurPtr) {
|
|||
}
|
||||
}
|
||||
|
||||
if (CurPtr == BufferEnd+1) { --CurPtr; break; }
|
||||
if (CurPtr == BufferEnd+1) {
|
||||
if (PP && PP->isCodeCompletionFile(FileLoc))
|
||||
PP->CodeCompleteNaturalLanguage();
|
||||
|
||||
--CurPtr;
|
||||
break;
|
||||
}
|
||||
} while (C != '\n' && C != '\r');
|
||||
|
||||
// Found but did not consume the newline. Notify comment handlers about the
|
||||
|
@ -1424,7 +1433,9 @@ bool Lexer::SkipBlockComment(Token &Result, const char *CurPtr) {
|
|||
Diag(CurPtr-1, diag::warn_nested_block_comment);
|
||||
}
|
||||
} else if (C == 0 && CurPtr == BufferEnd+1) {
|
||||
if (!isLexingRawMode() && !PP->isCodeCompletionFile(FileLoc))
|
||||
if (PP && PP->isCodeCompletionFile(FileLoc))
|
||||
PP->CodeCompleteNaturalLanguage();
|
||||
else if (!isLexingRawMode())
|
||||
Diag(BufferPtr, diag::err_unterminated_block_comment);
|
||||
// Note: the user probably forgot a */. We could continue immediately
|
||||
// after the /*, but this would involve lexing a lot of what really is the
|
||||
|
@ -1510,6 +1521,11 @@ std::string Lexer::ReadToEndOfLine() {
|
|||
|
||||
// Next, lex the character, which should handle the EOM transition.
|
||||
Lex(Tmp);
|
||||
if (Tmp.is(tok::code_completion)) {
|
||||
if (PP && PP->getCodeCompletionHandler())
|
||||
PP->getCodeCompletionHandler()->CodeCompleteNaturalLanguage();
|
||||
Lex(Tmp);
|
||||
}
|
||||
assert(Tmp.is(tok::eom) && "Unexpected token!");
|
||||
|
||||
// Finally, we're done, return the string we found.
|
||||
|
|
|
@ -284,6 +284,13 @@ bool Preprocessor::isCodeCompletionFile(SourceLocation FileLoc) const {
|
|||
== CodeCompletionFile;
|
||||
}
|
||||
|
||||
void Preprocessor::CodeCompleteNaturalLanguage() {
|
||||
SetCodeCompletionPoint(0, 0, 0);
|
||||
getDiagnostics().setSuppressAllDiagnostics(true);
|
||||
if (CodeComplete)
|
||||
CodeComplete->CodeCompleteNaturalLanguage();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Token Spelling
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -1154,3 +1154,7 @@ void Parser::CodeCompleteMacroArgument(IdentifierInfo *Macro,
|
|||
Actions.CodeCompletePreprocessorMacroArgument(getCurScope(), Macro, MacroInfo,
|
||||
ArgumentIndex);
|
||||
}
|
||||
|
||||
void Parser::CodeCompleteNaturalLanguage() {
|
||||
Actions.CodeCompleteNaturalLanguage();
|
||||
}
|
||||
|
|
|
@ -4873,6 +4873,13 @@ void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
|
|||
: Action::PCC_Namespace);
|
||||
}
|
||||
|
||||
void Sema::CodeCompleteNaturalLanguage() {
|
||||
// FIXME: Use a dedicated completion context for this!
|
||||
HandleCodeCompleteResults(this, CodeCompleter,
|
||||
CodeCompletionContext::CCC_Other,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
void Sema::GatherGlobalCodeCompletions(
|
||||
llvm::SmallVectorImpl<CodeCompletionResult> &Results) {
|
||||
ResultBuilder Builder(*this);
|
||||
|
|
|
@ -52,10 +52,6 @@ void f4(const char* str) {
|
|||
// CHECK-CC4: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50)
|
||||
// CHECK-CC4: VarDecl:{ResultType struct X}{TypedText f1} (50) (deprecated)
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:13:28 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC5 %s
|
||||
// CHECK-CC5: NotImplemented:{TypedText void} (65)
|
||||
// CHECK-CC5: NotImplemented:{TypedText volatile} (65)
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:19:3 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC6 %s
|
||||
// CHECK-CC6: FunctionDecl:{ResultType void}{TypedText f3}{LeftParen (}{Placeholder char const *}{Placeholder , ...}{Text , NULL}{RightParen )} (45)
|
||||
// CHECK-CC6: NotImplemented:{TypedText void} (65)
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// Note: the run lines follow their respective tests, since line/column
|
||||
// matter in this test.
|
||||
|
||||
const char *in_string = "string";
|
||||
char in_char = 'a';
|
||||
// in comment
|
||||
/* in comment */
|
||||
#warning blarg
|
||||
#error blarg
|
||||
#pragma mark this is the spot
|
||||
// RUN: c-index-test -code-completion-at=%s:4:32 %s > %t
|
||||
// RUN: echo "DONE" >> %t
|
||||
// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
|
||||
// CHECK-CC1-NOT: :
|
||||
// CHECK-CC1: DONE
|
||||
// RUN: c-index-test -code-completion-at=%s:5:18 %s > %t
|
||||
// RUN: echo "DONE" >> %t
|
||||
// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
|
||||
// RUN: c-index-test -code-completion-at=%s:6:7 %s > %t
|
||||
// RUN: echo "DONE" >> %t
|
||||
// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
|
||||
// RUN: c-index-test -code-completion-at=%s:7:7 %s > %t
|
||||
// RUN: echo "DONE" >> %t
|
||||
// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
|
||||
// RUN: c-index-test -code-completion-at=%s:8:10 %s > %t
|
||||
// RUN: echo "DONE" >> %t
|
||||
// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
|
||||
// RUN: c-index-test -code-completion-at=%s:9:9 %s > %t
|
||||
// RUN: echo "DONE" >> %t
|
||||
// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
|
||||
// RUN: c-index-test -code-completion-at=%s:10:19 %s > %t
|
||||
// RUN: echo "DONE" >> %t
|
||||
// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
|
||||
|
Загрузка…
Ссылка в новой задаче