forked from OSchip/llvm-project
[clangd] Collect location of macro definition in the ParsedAST
allows semantic hightlighting macro definition Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D67264 llvm-svn: 371504
This commit is contained in:
parent
664d9d2da2
commit
8dd26fd84e
|
@ -98,23 +98,30 @@ private:
|
|||
std::vector<Decl *> TopLevelDecls;
|
||||
};
|
||||
|
||||
// This collects macro expansions in the main file.
|
||||
// This collects macro expansions/definitions in the main file.
|
||||
// (Contrast with CollectMainFileMacros in Preamble.cpp, which collects macro
|
||||
// *definitions* in the preamble region of the main file).
|
||||
class CollectMainFileMacroExpansions : public PPCallbacks {
|
||||
class CollectMainFileMacros : public PPCallbacks {
|
||||
const SourceManager &SM;
|
||||
std::vector<SourceLocation> &MainFileMacroLocs;
|
||||
|
||||
void addLoc(SourceLocation Loc) {
|
||||
if (!Loc.isMacroID() && isInsideMainFile(Loc, SM))
|
||||
MainFileMacroLocs.push_back(Loc);
|
||||
}
|
||||
|
||||
public:
|
||||
CollectMainFileMacroExpansions(const SourceManager &SM,
|
||||
std::vector<SourceLocation> &MainFileMacroLocs)
|
||||
CollectMainFileMacros(const SourceManager &SM,
|
||||
std::vector<SourceLocation> &MainFileMacroLocs)
|
||||
: SM(SM), MainFileMacroLocs(MainFileMacroLocs) {}
|
||||
|
||||
void MacroDefined(const Token &MacroNameTok,
|
||||
const MacroDirective *MD) override {
|
||||
addLoc(MacroNameTok.getLocation());
|
||||
}
|
||||
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
|
||||
SourceRange Range, const MacroArgs *Args) override {
|
||||
SourceLocation L = MacroNameTok.getLocation();
|
||||
if (!L.isMacroID() && isInsideMainFile(L, SM))
|
||||
MainFileMacroLocs.push_back(L);
|
||||
addLoc(MacroNameTok.getLocation());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -358,8 +365,8 @@ ParsedAST::build(std::unique_ptr<clang::CompilerInvocation> CI,
|
|||
// Collect the macro expansions in the main file.
|
||||
std::vector<SourceLocation> MainFileMacroExpLocs;
|
||||
Clang->getPreprocessor().addPPCallbacks(
|
||||
std::make_unique<CollectMainFileMacroExpansions>(
|
||||
Clang->getSourceManager(), MainFileMacroExpLocs));
|
||||
std::make_unique<CollectMainFileMacros>(Clang->getSourceManager(),
|
||||
MainFileMacroExpLocs));
|
||||
|
||||
// Copy over the includes from the preamble, then combine with the
|
||||
// non-preamble includes below.
|
||||
|
@ -453,8 +460,8 @@ llvm::ArrayRef<Decl *> ParsedAST::getLocalTopLevelDecls() {
|
|||
return LocalTopLevelDecls;
|
||||
}
|
||||
|
||||
llvm::ArrayRef<SourceLocation> ParsedAST::getMainFileExpansions() const {
|
||||
return MainFileMacroExpLocs;
|
||||
llvm::ArrayRef<SourceLocation> ParsedAST::getMacros() const {
|
||||
return MacroIdentifierLocs;
|
||||
}
|
||||
|
||||
const std::vector<Diag> &ParsedAST::getDiagnostics() const { return Diags; }
|
||||
|
@ -503,13 +510,13 @@ ParsedAST::ParsedAST(std::shared_ptr<const PreambleData> Preamble,
|
|||
std::unique_ptr<CompilerInstance> Clang,
|
||||
std::unique_ptr<FrontendAction> Action,
|
||||
syntax::TokenBuffer Tokens,
|
||||
std::vector<SourceLocation> MainFileMacroExpLocs,
|
||||
std::vector<SourceLocation> MacroIdentifierLocs,
|
||||
std::vector<Decl *> LocalTopLevelDecls,
|
||||
std::vector<Diag> Diags, IncludeStructure Includes,
|
||||
CanonicalIncludes CanonIncludes)
|
||||
: Preamble(std::move(Preamble)), Clang(std::move(Clang)),
|
||||
Action(std::move(Action)), Tokens(std::move(Tokens)),
|
||||
MainFileMacroExpLocs(std::move(MainFileMacroExpLocs)),
|
||||
MacroIdentifierLocs(std::move(MacroIdentifierLocs)),
|
||||
Diags(std::move(Diags)),
|
||||
LocalTopLevelDecls(std::move(LocalTopLevelDecls)),
|
||||
Includes(std::move(Includes)), CanonIncludes(std::move(CanonIncludes)) {
|
||||
|
|
|
@ -89,9 +89,10 @@ public:
|
|||
const IncludeStructure &getIncludeStructure() const;
|
||||
const CanonicalIncludes &getCanonicalIncludes() const;
|
||||
|
||||
/// The start locations of all macro expansions spelled inside the main file.
|
||||
/// Does not include expansions from inside other macro expansions.
|
||||
llvm::ArrayRef<SourceLocation> getMainFileExpansions() const;
|
||||
/// Gets all macro locations (definition, expansions) present in the main
|
||||
/// file.
|
||||
/// NOTE: macros inside the preamble are not included.
|
||||
llvm::ArrayRef<SourceLocation> getMacros() const;
|
||||
/// Tokens recorded while parsing the main file.
|
||||
/// (!) does not have tokens from the preamble.
|
||||
const syntax::TokenBuffer &getTokens() const { return Tokens; }
|
||||
|
@ -120,9 +121,10 @@ private:
|
|||
/// - Does not have spelled or expanded tokens for files from preamble.
|
||||
syntax::TokenBuffer Tokens;
|
||||
|
||||
/// The start locations of all macro expansions spelled inside the main file.
|
||||
/// Does not include expansions from inside other macro expansions.
|
||||
std::vector<SourceLocation> MainFileMacroExpLocs;
|
||||
/// The start locations of all macro definitions/expansions spelled **after**
|
||||
/// preamble.
|
||||
/// Does not include locations from inside other macro expansions.
|
||||
std::vector<SourceLocation> MacroIdentifierLocs;
|
||||
// Data, stored after parsing.
|
||||
std::vector<Diag> Diags;
|
||||
// Top-level decls inside the current file. Not that this does not include
|
||||
|
|
|
@ -38,10 +38,8 @@ public:
|
|||
TraverseAST(AST.getASTContext());
|
||||
// Add highlightings for macro expansions as they are not traversed by the
|
||||
// visitor.
|
||||
// FIXME: Should add highlighting to the macro definitions as well. But this
|
||||
// information is not collected in ParsedAST right now.
|
||||
for (const SourceLocation &L : AST.getMainFileExpansions())
|
||||
addToken(L, HighlightingKind::Macro);
|
||||
for (SourceLocation Loc : AST.getMacros())
|
||||
addToken(Loc, HighlightingKind::Macro);
|
||||
// Initializer lists can give duplicates of tokens, therefore all tokens
|
||||
// must be deduplicated.
|
||||
llvm::sort(Tokens);
|
||||
|
|
|
@ -230,26 +230,28 @@ TEST(ParsedASTTest, CanBuildInvocationWithUnknownArgs) {
|
|||
TEST(ParsedASTTest, CollectsMainFileMacroExpansions) {
|
||||
Annotations TestCase(R"cpp(
|
||||
#define MACRO_ARGS(X, Y) X Y
|
||||
// - premable ends, macros inside preamble are not considered in main file.
|
||||
^ID(int A);
|
||||
// Macro arguments included.
|
||||
^MACRO_ARGS(^MACRO_ARGS(^MACRO_EXP(int), A), ^ID(= 2));
|
||||
|
||||
// Macro names inside other macros not included.
|
||||
#define FOO BAR
|
||||
#define BAR 1
|
||||
#define ^MACRO_ARGS2(X, Y) X Y
|
||||
#define ^FOO BAR
|
||||
#define ^BAR 1
|
||||
int A = ^FOO;
|
||||
|
||||
// Macros from token concatenations not included.
|
||||
#define CONCAT(X) X##A()
|
||||
#define PREPEND(X) MACRO##X()
|
||||
#define MACROA() 123
|
||||
#define ^CONCAT(X) X##A()
|
||||
#define ^PREPEND(X) MACRO##X()
|
||||
#define ^MACROA() 123
|
||||
int B = ^CONCAT(MACRO);
|
||||
int D = ^PREPEND(A)
|
||||
|
||||
// Macros included not from preamble not included.
|
||||
#include "foo.inc"
|
||||
|
||||
#define assert(COND) if (!(COND)) { printf("%s", #COND); exit(0); }
|
||||
#define ^assert(COND) if (!(COND)) { printf("%s", #COND); exit(0); }
|
||||
|
||||
void test() {
|
||||
// Includes macro expansions in arguments that are expressions
|
||||
|
@ -268,8 +270,7 @@ TEST(ParsedASTTest, CollectsMainFileMacroExpansions) {
|
|||
int D = DEF;
|
||||
)cpp";
|
||||
ParsedAST AST = TU.build();
|
||||
const std::vector<SourceLocation> &MacroExpansionLocations =
|
||||
AST.getMainFileExpansions();
|
||||
const std::vector<SourceLocation> &MacroExpansionLocations = AST.getMacros();
|
||||
std::vector<Position> MacroExpansionPositions;
|
||||
for (const auto &L : MacroExpansionLocations)
|
||||
MacroExpansionPositions.push_back(
|
||||
|
|
|
@ -427,18 +427,19 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
|
|||
R"cpp(
|
||||
#define DEF_MULTIPLE(X) namespace X { class X { int X; }; }
|
||||
#define DEF_CLASS(T) class T {};
|
||||
// Preamble ends.
|
||||
$Macro[[DEF_MULTIPLE]](XYZ);
|
||||
$Macro[[DEF_MULTIPLE]](XYZW);
|
||||
$Macro[[DEF_CLASS]]($Class[[A]])
|
||||
#define MACRO_CONCAT(X, V, T) T foo##X = V
|
||||
#define DEF_VAR(X, V) int X = V
|
||||
#define DEF_VAR_T(T, X, V) T X = V
|
||||
#define DEF_VAR_REV(V, X) DEF_VAR(X, V)
|
||||
#define CPY(X) X
|
||||
#define DEF_VAR_TYPE(X, Y) X Y
|
||||
#define SOME_NAME variable
|
||||
#define SOME_NAME_SET variable2 = 123
|
||||
#define INC_VAR(X) X += 2
|
||||
#define $Macro[[MACRO_CONCAT]](X, V, T) T foo##X = V
|
||||
#define $Macro[[DEF_VAR]](X, V) int X = V
|
||||
#define $Macro[[DEF_VAR_T]](T, X, V) T X = V
|
||||
#define $Macro[[DEF_VAR_REV]](V, X) DEF_VAR(X, V)
|
||||
#define $Macro[[CPY]](X) X
|
||||
#define $Macro[[DEF_VAR_TYPE]](X, Y) X Y
|
||||
#define $Macro[[SOME_NAME]] variable
|
||||
#define $Macro[[SOME_NAME_SET]] variable2 = 123
|
||||
#define $Macro[[INC_VAR]](X) X += 2
|
||||
$Primitive[[void]] $Function[[foo]]() {
|
||||
$Macro[[DEF_VAR]]($LocalVariable[[X]], 123);
|
||||
$Macro[[DEF_VAR_REV]](908, $LocalVariable[[XY]]);
|
||||
|
@ -457,8 +458,8 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
|
|||
$Macro[[DEF_VAR]]($Variable[[XYZ]], 567);
|
||||
$Macro[[DEF_VAR_REV]](756, $Variable[[AB]]);
|
||||
|
||||
#define CALL_FN(F) F();
|
||||
#define DEF_FN(F) void F ()
|
||||
#define $Macro[[CALL_FN]](F) F();
|
||||
#define $Macro[[DEF_FN]](F) void F ()
|
||||
$Macro[[DEF_FN]]($Function[[g]]) {
|
||||
$Macro[[CALL_FN]]($Function[[foo]]);
|
||||
}
|
||||
|
@ -466,6 +467,7 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
|
|||
R"cpp(
|
||||
#define fail(expr) expr
|
||||
#define assert(COND) if (!(COND)) { fail("assertion failed" #COND); }
|
||||
// Preamble ends.
|
||||
$Primitive[[int]] $Variable[[x]];
|
||||
$Primitive[[int]] $Variable[[y]];
|
||||
$Primitive[[int]] $Function[[f]]();
|
||||
|
|
Loading…
Reference in New Issue