Index: include-fixer/IncludeFixer.cpp =================================================================== --- include-fixer/IncludeFixer.cpp +++ include-fixer/IncludeFixer.cpp @@ -37,7 +37,6 @@ std::unique_ptr CreateASTConsumer(clang::CompilerInstance &Compiler, StringRef InFile) override { - Filename = InFile; return llvm::make_unique(); } @@ -188,8 +187,6 @@ return clang::TypoCorrection(); } - StringRef filename() const { return Filename; } - /// Get the minimal include for a given path. std::string minimizeInclude(StringRef Include, const clang::SourceManager &SourceManager, @@ -230,8 +227,7 @@ Symbol.getContexts(), Symbol.getNumOccurrences()); } - return IncludeFixerContext(QuerySymbol, SymbolScopedQualifiers, - SymbolCandidates, QuerySymbolRange); + return IncludeFixerContext(QuerySymbolInfo, SymbolCandidates); } private: @@ -252,9 +248,7 @@ .print(llvm::dbgs(), getCompilerInstance().getSourceManager())); DEBUG(llvm::dbgs() << " ..."); - QuerySymbol = Query.str(); - QuerySymbolRange = Range; - SymbolScopedQualifiers = ScopedQualifiers; + QuerySymbolInfo = {Query.str(), ScopedQualifiers, Range}; // Query the symbol based on C++ name Lookup rules. // Firstly, lookup the identifier with scoped namespace contexts; @@ -280,19 +274,8 @@ /// The client to use to find cross-references. SymbolIndexManager &SymbolIndexMgr; - /// The absolute path to the file being processed. - std::string Filename; - - /// The symbol being queried. - std::string QuerySymbol; - - /// The scoped qualifiers of QuerySymbol. It is represented as a sequence of - /// names and scope resolution operatiors ::, ending with a scope resolution - /// operator (e.g. a::b::). Empty if the symbol is not in a specific scope. - std::string SymbolScopedQualifiers; - - /// The replacement range of the first discovered QuerySymbol. - tooling::Range QuerySymbolRange; + /// The symbol information. + IncludeFixerContext::QuerySymbolInfo QuerySymbolInfo; /// All symbol candidates which match QuerySymbol. We only include the first /// discovered identifier to avoid getting caught in results from error Index: include-fixer/IncludeFixerContext.h =================================================================== --- include-fixer/IncludeFixerContext.h +++ include-fixer/IncludeFixerContext.h @@ -21,11 +21,6 @@ /// \brief A context for the symbol being queried. class IncludeFixerContext { public: - IncludeFixerContext() = default; - IncludeFixerContext(llvm::StringRef Name, llvm::StringRef ScopeQualifiers, - const std::vector Symbols, - tooling::Range Range); - struct HeaderInfo { /// \brief The header where QualifiedName comes from. std::string Header; @@ -34,36 +29,48 @@ std::string QualifiedName; }; + struct QuerySymbolInfo { + /// \brief The raw symbol name being queried in database. This name might + /// miss some namespace qualifiers, and will be replaced by a fully + /// qualified one. + std::string RawIdentifier; + + /// \brief The qualifiers of the scope in which SymbolIdentifier lookup + /// occurs. It is represented as a sequence of names and scope resolution + /// operatiors ::, ending with a scope resolution operator (e.g. a::b::). + /// Empty if SymbolIdentifier is not in a specific scope. + std::string ScopedQualifiers; + + /// \brief The replacement range of RawIdentifier. + tooling::Range Range; + }; + + IncludeFixerContext() = default; + IncludeFixerContext(const QuerySymbolInfo &QuerySymbol, + const std::vector Symbols); + /// \brief Get symbol name. - llvm::StringRef getSymbolIdentifier() const { return SymbolIdentifier; } + llvm::StringRef getSymbolIdentifier() const { + return QuerySymbol.RawIdentifier; + } /// \brief Get replacement range of the symbol. - tooling::Range getSymbolRange() const { return SymbolRange; } + tooling::Range getSymbolRange() const { return QuerySymbol.Range; } const std::vector &getHeaderInfos() const { return HeaderInfos; } private: friend struct llvm::yaml::MappingTraits; - /// \brief The raw symbol name being queried in database. This name might miss - /// some namespace qualifiers, and will be replaced by a fully qualified one. - std::string SymbolIdentifier; - - /// \brief The qualifiers of the scope in which SymbolIdentifier lookup - /// occurs. It is represented as a sequence of names and scope resolution - /// operatiors ::, ending with a scope resolution operator (e.g. a::b::). - /// Empty if SymbolIdentifier is not in a specific scope. - std::string SymbolScopedQualifiers; - /// \brief The symbol candidates which match SymbolIdentifier. The symbols are /// sorted in a descending order based on the popularity info in SymbolInfo. std::vector MatchedSymbols; - /// \brief The replacement range of SymbolIdentifier. - tooling::Range SymbolRange; - /// \brief The header information. std::vector HeaderInfos; + + /// \brief The information of the symbol being queried. + QuerySymbolInfo QuerySymbol; }; } // namespace include_fixer Index: include-fixer/IncludeFixerContext.cpp =================================================================== --- include-fixer/IncludeFixerContext.cpp +++ include-fixer/IncludeFixerContext.cpp @@ -75,15 +75,14 @@ } // anonymous namespace IncludeFixerContext::IncludeFixerContext( - llvm::StringRef Name, llvm::StringRef ScopeQualifiers, - std::vector Symbols, - tooling::Range Range) - : SymbolIdentifier(Name), SymbolScopedQualifiers(ScopeQualifiers), - MatchedSymbols(std::move(Symbols)), SymbolRange(Range) { + const QuerySymbolInfo &QuerySymbol, + const std::vector Symbols) + : MatchedSymbols(std::move(Symbols)), QuerySymbol(QuerySymbol) { for (const auto &Symbol : MatchedSymbols) { - HeaderInfos.push_back({Symbol.getFilePath().str(), - createQualifiedNameForReplacement( - SymbolIdentifier, ScopeQualifiers, Symbol)}); + HeaderInfos.push_back( + {Symbol.getFilePath().str(), + createQualifiedNameForReplacement( + QuerySymbol.RawIdentifier, QuerySymbol.ScopedQualifiers, Symbol)}); } // Deduplicate header infos. HeaderInfos.erase(std::unique(HeaderInfos.begin(), HeaderInfos.end(), Index: include-fixer/tool/ClangIncludeFixer.cpp =================================================================== --- include-fixer/tool/ClangIncludeFixer.cpp +++ include-fixer/tool/ClangIncludeFixer.cpp @@ -61,11 +61,17 @@ } }; +template <> struct MappingTraits { + static void mapping(IO &io, IncludeFixerContext::QuerySymbolInfo &Info) { + io.mapRequired("RawIdentifier", Info.RawIdentifier); + io.mapRequired("Range", Info.Range); + } +}; + template <> struct MappingTraits { static void mapping(IO &IO, IncludeFixerContext &Context) { - IO.mapRequired("SymbolIdentifier", Context.SymbolIdentifier); + IO.mapRequired("QuerySymbolInfo", Context.QuerySymbol); IO.mapRequired("HeaderInfos", Context.HeaderInfos); - IO.mapRequired("Range", Context.SymbolRange); } }; } // namespace yaml @@ -112,8 +118,10 @@ cl::desc("Print the symbol being queried and all its relevant headers in\n" "JSON format to stdout:\n" " {\n" - " \"SymbolIdentifier\": \"foo\",\n" - " \"Range\": {\"Offset\":0, \"Length\": 3},\n" + " \"QuerySymbolInfo\": {\n" + " \"RawIdentifier\": \"foo\",\n" + " \"Range\": {\"Offset\":0, \"Length\": 3}\n" + " },\n" " \"HeaderInfos\": [ {\"Header\": \"\\\"foo_a.h\\\"\",\n" " \"QualifiedName\": \"a::foo\"} ]\n" " }"), @@ -125,8 +133,10 @@ "The result is written to stdout. It is currently used for\n" "editor integration. Support YAML/JSON format:\n" " -insert-header=\"{\n" - " SymbolIdentifier: foo,\n" - " Range: {Offset: 0, Length: 3},\n" + " QuerySymbolInfo: {\n" + " RawIdentifier: foo,\n" + " Range: {Offset: 0, Length: 3}\n" + " },\n" " HeaderInfos: [ {Headers: \"\\\"foo_a.h\\\"\",\n" " QualifiedName: \"a::foo\"} ]}\""), cl::init(""), cl::cat(IncludeFixerCategory)); @@ -192,11 +202,13 @@ void writeToJson(llvm::raw_ostream &OS, const IncludeFixerContext& Context) { OS << "{\n" - " \"SymbolIdentifier\": \"" + " \"QuerySymbolInfo\": {\n" + " \"RawIdentifier\": \"" << Context.getSymbolIdentifier() << "\",\n"; - OS << " \"Range\": {"; + OS << " \"Range\": {"; OS << " \"Offset\":" << Context.getSymbolRange().getOffset() << ","; - OS << " \"Length\":" << Context.getSymbolRange().getLength() << " },\n"; + OS << " \"Length\":" << Context.getSymbolRange().getLength() << " }\n"; + OS << " },\n"; OS << " \"HeaderInfos\": [\n"; const auto &HeaderInfos = Context.getHeaderInfos(); for (const auto &Info : HeaderInfos) { Index: include-fixer/tool/clang-include-fixer.py =================================================================== --- include-fixer/tool/clang-include-fixer.py +++ include-fixer/tool/clang-include-fixer.py @@ -127,7 +127,8 @@ return include_fixer_context = json.loads(stdout) - symbol = include_fixer_context["SymbolIdentifier"] + query_symbol_info = include_fixer_context["QuerySymbolInfo"] + symbol = query_symbol_info["RawIdentifier"] # The header_infos is already sorted by include-fixer. header_infos = include_fixer_context["HeaderInfos"] # Deduplicate headers while keeping the order, so that the same header would @@ -151,8 +152,7 @@ try: # If there is only one suggested header, insert it directly. if len(unique_headers) == 1 or maximum_suggested_headers == 1: - InsertHeaderToVimBuffer({"SymbolIdentifier": symbol, - "Range": include_fixer_context["Range"], + InsertHeaderToVimBuffer({"QuerySymbolInfo": query_symbol_info, "HeaderInfos": header_infos}, text) print "Added #include {0} for {1}.".format(unique_headers[0], symbol) return @@ -163,8 +163,7 @@ header for header in header_infos if header["Header"] == selected] # Insert a selected header. - InsertHeaderToVimBuffer({"SymbolIdentifier": symbol, - "Range": include_fixer_context["Range"], + InsertHeaderToVimBuffer({"QuerySymbolInfo": query_symbol_info, "HeaderInfos": selected_header_infos}, text) print "Added #include {0} for {1}.".format(selected, symbol) except Exception as error: Index: test/include-fixer/commandline_options.cpp =================================================================== --- test/include-fixer/commandline_options.cpp +++ test/include-fixer/commandline_options.cpp @@ -1,9 +1,9 @@ // REQUIRES: shell // RUN: echo "foo f;" > %t.cpp // RUN: clang-include-fixer -db=fixed -input='foo= "foo.h","bar.h"' -output-headers %t.cpp -- | FileCheck %s -// RUN: cat %t.cpp | clang-include-fixer -stdin -insert-header='{SymbolIdentifier: foo, Range: {Offset: 0, Length: 3}, HeaderInfos: [{Header: "\"foo.h\"", QualifiedName: "foo"}]}' %t.cpp | FileCheck %s -check-prefix=CHECK-CODE -// RUN: cat %t.cpp | not clang-include-fixer -stdin -insert-header='{SymbolIdentifier: foo, Range: {Offset: 0, Length: 3}, HeaderInfos: [{Header: "\"foo.h\"", QualifiedName: "foo"},{Header: "\"foo2.h\"", QualifiedName: "foo"}]}' %t.cpp -// RUN: cat %t.cpp | clang-include-fixer -stdin -insert-header='{SymbolIdentifier: foo, Range: {Offset: 0, Length: 3}, HeaderInfos: [{Header: "\"foo.h\"", QualifiedName: "a:foo"},{Header: "\"foo.h\"", QualifiedName: "b:foo"}]}' %t.cpp +// RUN: cat %t.cpp | clang-include-fixer -stdin -insert-header='{QuerySymbolInfo: {RawIdentifier: foo, Range: {Offset: 0, Length: 3}}, HeaderInfos: [{Header: "\"foo.h\"", QualifiedName: "foo"}]}' %t.cpp | FileCheck %s -check-prefix=CHECK-CODE +// RUN: cat %t.cpp | not clang-include-fixer -stdin -insert-header='{QuerySymbolInfo: {RawIdentifier: foo, Range: {Offset: 0, Length: 3}}, HeaderInfos: [{Header: "\"foo.h\"", QualifiedName: "foo"},{Header: "\"foo2.h\"", QualifiedName: "foo"}]}' %t.cpp +// RUN: cat %t.cpp | clang-include-fixer -stdin -insert-header='{QuerySymbolInfo: {RawIdentifier: foo, Range: {Offset: 0, Length: 3}}, HeaderInfos: [{Header: "\"foo.h\"", QualifiedName: "a:foo"},{Header: "\"foo.h\"", QualifiedName: "b:foo"}]}' %t.cpp // // CHECK: "HeaderInfos": [ // CHECK-NEXT: {"Header": "\"foo.h\"",