Revert "[clang][ExtractAPI] Add ability to create multiple symbol graphs (#86676)"

This failed the test suite due to missing DiagGroup for a new warning.

This reverts commit b31414bf4f9898f7817a9fcf8a91f62ec26f3eaf.
This commit is contained in:
Daniel Grumberg 2024-04-02 15:34:52 +01:00
parent ea9a66ea8b
commit 209a1e8dfd
79 changed files with 8888 additions and 3931 deletions

View File

@ -548,12 +548,6 @@ def err_drv_extract_api_wrong_kind : Error<
"header file '%0' input '%1' does not match the type of prior input "
"in api extraction; use '-x %2' to override">;
def err_drv_missing_symbol_graph_dir: Error<
"Must provide a symbol graph output directory using --symbol-graph-dir=<directory>">;
def err_drv_unexpected_symbol_graph_output : Error<
"Unexpected output symbol graph '%1'; please provide --symbol-graph-dir=<directory> instead">;
def warn_slash_u_filename : Warning<"'/U%0' treated as the '/U' option">,
InGroup<DiagGroup<"slash-u-filename">>;
def note_use_dashdash : Note<

View File

@ -366,6 +366,4 @@ def warn_profile_data_misexpect : Warning<
def err_extract_api_ignores_file_not_found :
Error<"file '%0' specified by '--extract-api-ignores=' not found">, DefaultFatal;
def warn_missing_symbol_graph_dir : Warning<"Missing symbol graph output directory, defaulting to working directory">;
}

View File

@ -1507,29 +1507,14 @@ def extract_api : Flag<["-"], "extract-api">,
def product_name_EQ: Joined<["--"], "product-name=">,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoString<FrontendOpts<"ProductName">>;
def emit_symbol_graph: Flag<["-"], "emit-symbol-graph">,
def emit_symbol_graph_EQ: JoinedOrSeparate<["--"], "emit-symbol-graph=">,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Generate Extract API information as a side effect of compilation.">,
MarshallingInfoFlag<FrontendOpts<"EmitSymbolGraph">>;
def emit_extension_symbol_graphs: Flag<["--"], "emit-extension-symbol-graphs">,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Generate additional symbol graphs for extended modules.">,
MarshallingInfoFlag<FrontendOpts<"EmitExtensionSymbolGraphs">>;
HelpText<"Generate Extract API information as a side effect of compilation.">,
MarshallingInfoString<FrontendOpts<"SymbolGraphOutputDir">>;
def extract_api_ignores_EQ: CommaJoined<["--"], "extract-api-ignores=">,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Comma separated list of files containing a new line separated list of API symbols to ignore when extracting API information.">,
MarshallingInfoStringVector<FrontendOpts<"ExtractAPIIgnoresFileList">>;
def symbol_graph_dir_EQ: Joined<["--"], "symbol-graph-dir=">,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Directory in which to emit symbol graphs.">,
MarshallingInfoString<FrontendOpts<"SymbolGraphOutputDir">>;
def emit_pretty_sgf: Flag<["--"], "pretty-sgf">,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Emit pretty printed symbol graphs">,
MarshallingInfoFlag<FrontendOpts<"EmitPrettySymbolGraphs">>;
def emit_sgf_symbol_labels_for_testing: Flag<["--"], "emit-sgf-symbol-labels-for-testing">,
Visibility<[CC1Option]>,
MarshallingInfoFlag<FrontendOpts<"EmitSymbolGraphSymbolLabelsForTesting">>;
def e : Separate<["-"], "e">, Flags<[LinkerInput]>, Group<Link_Group>;
def fmax_tokens_EQ : Joined<["-"], "fmax-tokens=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,

File diff suppressed because it is too large Load Diff

View File

@ -1,103 +0,0 @@
//===- ExtractAPI/APIRecords.inc --------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file defines the classes defined from ExtractAPI's APIRecord
///
//===----------------------------------------------------------------------===//
#ifndef ABSTRACT_RECORD
#define ABSTRACT_RECORD(CLASS, BASE) RECORD(CLASS, BASE)
#endif
#ifndef CONCRETE_RECORD
#define CONCRETE_RECORD(CLASS, BASE, KIND) RECORD(CLASS, BASE)
#endif
#ifndef RECORD
#define RECORD(CLASS, BASE)
#endif
CONCRETE_RECORD(NamespaceRecord, APIRecord, RK_Namespace)
CONCRETE_RECORD(GlobalFunctionRecord, APIRecord, RK_GlobalFunction)
CONCRETE_RECORD(GlobalFunctionTemplateRecord, GlobalFunctionRecord,
RK_GlobalFunctionTemplate)
CONCRETE_RECORD(GlobalFunctionTemplateSpecializationRecord,
GlobalFunctionRecord, RK_GlobalFunctionTemplateSpecialization)
CONCRETE_RECORD(GlobalVariableRecord, APIRecord, RK_GlobalVariable)
CONCRETE_RECORD(GlobalVariableTemplateRecord, GlobalVariableRecord,
RK_GlobalVariableTemplate)
CONCRETE_RECORD(GlobalVariableTemplateSpecializationRecord,
GlobalVariableRecord, RK_GlobalVariableTemplateSpecialization)
CONCRETE_RECORD(GlobalVariableTemplatePartialSpecializationRecord,
GlobalVariableRecord,
RK_GlobalVariableTemplatePartialSpecialization)
CONCRETE_RECORD(EnumConstantRecord, APIRecord, RK_EnumConstant)
CONCRETE_RECORD(EnumRecord, APIRecord, RK_Enum)
ABSTRACT_RECORD(RecordFieldRecord, APIRecord)
ABSTRACT_RECORD(RecordRecord, APIRecord)
CONCRETE_RECORD(StructFieldRecord, RecordFieldRecord, RK_StructField)
CONCRETE_RECORD(StructRecord, APIRecord, RK_Struct)
CONCRETE_RECORD(UnionFieldRecord, RecordFieldRecord, RK_UnionField)
CONCRETE_RECORD(UnionRecord, APIRecord, RK_Union)
CONCRETE_RECORD(CXXFieldRecord, APIRecord, RK_CXXField)
CONCRETE_RECORD(CXXFieldTemplateRecord, CXXFieldRecord, RK_CXXFieldTemplate)
ABSTRACT_RECORD(CXXMethodRecord, APIRecord)
CONCRETE_RECORD(CXXConstructorRecord, CXXMethodRecord, RK_CXXConstructorMethod)
CONCRETE_RECORD(CXXDestructorRecord, CXXMethodRecord, RK_CXXDestructorMethod)
CONCRETE_RECORD(CXXStaticMethodRecord, CXXMethodRecord, RK_CXXStaticMethod)
CONCRETE_RECORD(CXXInstanceMethodRecord, CXXMethodRecord, RK_CXXInstanceMethod)
CONCRETE_RECORD(CXXMethodTemplateRecord, CXXMethodRecord, RK_CXXMethodTemplate)
CONCRETE_RECORD(CXXMethodTemplateSpecializationRecord, CXXMethodRecord,
RK_CXXMethodTemplateSpecialization)
ABSTRACT_RECORD(ObjCPropertyRecord, APIRecord)
CONCRETE_RECORD(ObjCInstancePropertyRecord, ObjCPropertyRecord,
RK_ObjCInstanceProperty)
CONCRETE_RECORD(ObjCClassPropertyRecord, ObjCPropertyRecord,
RK_ObjCClassProperty)
CONCRETE_RECORD(ObjCInstanceVariableRecord, APIRecord, RK_ObjCIvar)
ABSTRACT_RECORD(ObjCMethodRecord, APIRecord)
CONCRETE_RECORD(ObjCInstanceMethodRecord, ObjCMethodRecord,
RK_ObjCInstanceMethod)
CONCRETE_RECORD(ObjCClassMethodRecord, ObjCMethodRecord, RK_ObjCClassMethod)
CONCRETE_RECORD(StaticFieldRecord, CXXFieldRecord, RK_StaticField)
ABSTRACT_RECORD(ObjCContainerRecord, APIRecord)
CONCRETE_RECORD(CXXClassRecord, APIRecord, RK_CXXClass)
CONCRETE_RECORD(ClassTemplateRecord, CXXClassRecord, RK_ClassTemplate)
CONCRETE_RECORD(ClassTemplateSpecializationRecord, CXXClassRecord,
RK_ClassTemplateSpecialization)
CONCRETE_RECORD(ClassTemplatePartialSpecializationRecord, CXXClassRecord,
RK_ClassTemplatePartialSpecialization)
CONCRETE_RECORD(ConceptRecord, APIRecord, RK_Concept)
CONCRETE_RECORD(ObjCCategoryRecord, ObjCContainerRecord, RK_ObjCCategory)
CONCRETE_RECORD(ObjCInterfaceRecord, ObjCContainerRecord, RK_ObjCInterface)
CONCRETE_RECORD(ObjCProtocolRecord, ObjCContainerRecord, RK_ObjCProtocol)
CONCRETE_RECORD(MacroDefinitionRecord, APIRecord, RK_MacroDefinition)
CONCRETE_RECORD(TypedefRecord, APIRecord, RK_Typedef)
#undef CONCRETE_RECORD
#undef ABSTRACT_RECORD
#undef RECORD
#ifndef RECORD_CONTEXT
#define RECORD_CONTEXT(CLASS, KIND)
#endif
RECORD_CONTEXT(NamespaceRecord, RK_Namespace)
RECORD_CONTEXT(EnumRecord, RK_Enum)
RECORD_CONTEXT(StructRecord, RK_Struct)
RECORD_CONTEXT(UnionRecord, RK_Union)
RECORD_CONTEXT(ObjCCategoryRecord, RK_ObjCCategory)
RECORD_CONTEXT(ObjCInterfaceRecord, RK_ObjCInterface)
RECORD_CONTEXT(ObjCProtocolRecord, RK_ObjCProtocol)
RECORD_CONTEXT(CXXClassRecord, RK_CXXClass)
RECORD_CONTEXT(ClassTemplateRecord, RK_ClassTemplate)
RECORD_CONTEXT(ClassTemplateSpecializationRecord,
RK_ClassTemplateSpecialization)
RECORD_CONTEXT(ClassTemplatePartialSpecializationRecord,
RK_ClassTemplatePartialSpecialization)
#undef RECORD_CONTEXT

View File

@ -182,18 +182,6 @@ public:
/// appending to chain up consecutive appends.
DeclarationFragments &appendSpace();
/// Append a text Fragment of a semicolon character.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive appends.
DeclarationFragments &appendSemicolon();
/// Removes a trailing semicolon character if present.
///
/// \returns a reference to the DeclarationFragments object itself after
/// removing to chain up consecutive operations.
DeclarationFragments &removeTrailingSemicolon();
/// Get the string description of a FragmentKind \p Kind.
static StringRef getFragmentKindString(FragmentKind Kind);
@ -206,14 +194,12 @@ public:
static DeclarationFragments getStructureTypeFragment(const RecordDecl *Decl);
private:
DeclarationFragments &appendUnduplicatedTextCharacter(char Character);
std::vector<Fragment> Fragments;
};
class AccessControl {
public:
AccessControl(std::string Access) : Access(Access) {}
AccessControl() : Access("public") {}
const std::string &getAccess() const { return Access; }

View File

@ -17,8 +17,6 @@
#include "clang/ExtractAPI/API.h"
#include "clang/ExtractAPI/APIIgnoresList.h"
#include "clang/Frontend/CompilerInstance.h"
#include "llvm/Support/raw_ostream.h"
namespace clang {
@ -31,8 +29,8 @@ protected:
/// A representation of the APIs this action extracts.
std::unique_ptr<extractapi::APISet> API;
/// A stream to the main output file of this action.
std::unique_ptr<llvm::raw_pwrite_stream> OS;
/// A stream to the output file of this action.
std::unique_ptr<raw_pwrite_stream> OS;
/// The product this action is extracting API information for.
std::string ProductName;
@ -48,7 +46,7 @@ protected:
///
/// Use the serializer to generate output symbol graph files from
/// the information gathered during the execution of Action.
void ImplEndSourceFileAction(CompilerInstance &CI);
void ImplEndSourceFileAction();
};
} // namespace clang

File diff suppressed because it is too large Load Diff

View File

@ -49,6 +49,9 @@ private:
void EndSourceFileAction() override;
static StringRef getInputBufferName() { return "<extract-api-includes>"; }
static std::unique_ptr<llvm::raw_pwrite_stream>
CreateOutputFile(CompilerInstance &CI, StringRef InFile);
};
/// Wrap ExtractAPIAction on top of a pre-existing action
@ -82,6 +85,9 @@ private:
/// actions. This is the place where all the gathered symbol graph
/// information is emited.
void EndSourceFileAction() override;
static std::unique_ptr<llvm::raw_pwrite_stream>
CreateOutputFile(CompilerInstance &CI, StringRef InFile);
};
} // namespace clang

View File

@ -1,172 +0,0 @@
//===- ExtractAPI/Serialization/APISetVisitor.h ----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file defines the ExtractAPI APISetVisitor interface.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
#define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
#include "clang/ExtractAPI/API.h"
namespace clang {
namespace extractapi {
// A helper macro to implement short-circuiting when recursing. It
// invokes CALL_EXPR, which must be a method call, on the derived
// object (s.t. a user of RecursiveASTVisitor can override the method
// in CALL_EXPR).
#define TRY_TO(CALL_EXPR) \
do { \
if (!getDerived()->CALL_EXPR) \
return false; \
} while (false)
/// The base interface of visitors for API information, the interface and usage
/// is almost identical to RecurisveASTVistor. This class performs three
/// distinct tasks:
/// 1. traverse the APISet (i.e. go to every record);
/// 2. at a given record, walk up the class hierarchy starting from the record's
/// dynamic type until APIRecord is reached.
/// 3. given a (record, class) combination where 'class' is some base class of
/// the dynamic type of 'record', call a user-overridable function to actually
/// visit the record.
///
/// These tasks are done by three groups of methods, respectively:
/// 1. traverseRecord(APIRecord *x) does task #1, it is the entry point for
/// traversing the records starting from x. This method simply forwards to
/// traverseFoo(Foo *x) where Foo is the dynamic type of *x, which calls
/// walkUpFromFoo(x) and then recursively visits the child records of x.
/// 2. walkUpFromFoo(Foo *x) does task #2. It doesn't visit children records of
/// x, instead it first calls walkUpFromBar(x) where Bar is the direct parent
/// class of Foo (unless Foo has no parent) and then calls visitFoo(x).
/// 3. visitFoo(Foo *x) does task #3.
///
/// These three method groups are tiered (traverse* > walkUpFrom* >
/// visit*). A method (e.g. traverse*) may call methods from the same
/// tier (e.g. other traverse*) or one tier lower (e.g. walkUpFrom*).
/// It may not call methods from a higher tier.
///
/// Note that since walkUpFromFoo() calls walkUpFromBar() (where Bar
/// is Foo's super class) before calling visitFoo(), the result is
/// that the visit*() methods for a given record are called in the
/// top-down order (e.g. for a record of type ObjCInstancePropertyRecord, the
/// order will be visitRecord(), visitObjCPropertyRecord(), and then
/// visitObjCInstancePropertyRecord()).
///
/// This scheme guarantees that all visit*() calls for the same record
/// are grouped together. In other words, visit*() methods for different
/// records are never interleaved.
///
/// Clients of this visitor should subclass the visitor (providing
/// themselves as the template argument, using the curiously recurring
/// template pattern) and override any of the traverse*, walkUpFrom*,
/// and visit* methods for records where the visitor should customize
/// behavior. Most users only need to override visit*. Advanced
/// users may override traverse* and walkUpFrom* to implement custom
/// traversal strategies. Returning false from one of these overridden
/// functions will abort the entire traversal.
template <typename Derived> class APISetVisitor {
public:
bool traverseAPISet() {
for (const APIRecord *TLR : API.getTopLevelRecords()) {
TRY_TO(traverseAPIRecord(TLR));
}
return true;
}
bool traverseAPIRecord(const APIRecord *Record);
bool walkUpFromAPIRecord(const APIRecord *Record) {
TRY_TO(visitAPIRecord(Record));
return true;
}
bool visitAPIRecord(const APIRecord *Record) { return true; }
#define GENERATE_TRAVERSE_METHOD(CLASS, BASE) \
bool traverse##CLASS(const CLASS *Record) { \
TRY_TO(walkUpFrom##CLASS(Record)); \
TRY_TO(traverseRecordContext(dyn_cast<RecordContext>(Record))); \
return true; \
}
#define GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE) \
bool walkUpFrom##CLASS(const CLASS *Record) { \
TRY_TO(walkUpFrom##BASE(Record)); \
TRY_TO(visit##CLASS(Record)); \
return true; \
} \
bool visit##CLASS(const CLASS *Record) { return true; }
#define CONCRETE_RECORD(CLASS, BASE, KIND) \
GENERATE_TRAVERSE_METHOD(CLASS, BASE) \
GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE)
#define ABSTRACT_RECORD(CLASS, BASE) \
GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE)
#include "../APIRecords.inc"
#undef GENERATE_WALKUP_AND_VISIT_METHODS
#undef GENERATE_TRAVERSE_METHOD
bool traverseRecordContext(const RecordContext *);
protected:
const APISet &API;
public:
APISetVisitor() = delete;
APISetVisitor(const APISetVisitor &) = delete;
APISetVisitor(APISetVisitor &&) = delete;
APISetVisitor &operator=(const APISetVisitor &) = delete;
APISetVisitor &operator=(APISetVisitor &&) = delete;
protected:
APISetVisitor(const APISet &API) : API(API) {}
~APISetVisitor() = default;
Derived *getDerived() { return static_cast<Derived *>(this); };
};
template <typename Derived>
bool APISetVisitor<Derived>::traverseRecordContext(
const RecordContext *Context) {
if (!Context)
return true;
for (auto *Child : Context->records())
TRY_TO(traverseAPIRecord(Child));
return true;
}
template <typename Derived>
bool APISetVisitor<Derived>::traverseAPIRecord(const APIRecord *Record) {
switch (Record->getKind()) {
#define CONCRETE_RECORD(CLASS, BASE, KIND) \
case APIRecord::KIND: { \
TRY_TO(traverse##CLASS(static_cast<const CLASS *>(Record))); \
break; \
}
#include "../APIRecords.inc"
case APIRecord::RK_Unknown: {
TRY_TO(walkUpFromAPIRecord(static_cast<const APIRecord *>(Record)));
break;
}
default:
llvm_unreachable("API Record with uninstantiable kind");
}
return true;
}
} // namespace extractapi
} // namespace clang
#endif // LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H

View File

@ -0,0 +1,314 @@
//===- ExtractAPI/Serialization/SerializerBase.h ----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file defines the ExtractAPI APISetVisitor interface.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
#define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
#include "clang/ExtractAPI/API.h"
namespace clang {
namespace extractapi {
/// The base interface of visitors for API information.
template <typename Derived> class APISetVisitor {
public:
void traverseAPISet() {
getDerived()->traverseNamespaces();
getDerived()->traverseGlobalVariableRecords();
getDerived()->traverseGlobalFunctionRecords();
getDerived()->traverseEnumRecords();
getDerived()->traverseStaticFieldRecords();
getDerived()->traverseCXXClassRecords();
getDerived()->traverseClassTemplateRecords();
getDerived()->traverseClassTemplateSpecializationRecords();
getDerived()->traverseClassTemplatePartialSpecializationRecords();
getDerived()->traverseCXXInstanceMethods();
getDerived()->traverseCXXStaticMethods();
getDerived()->traverseCXXMethodTemplates();
getDerived()->traverseCXXMethodTemplateSpecializations();
getDerived()->traverseCXXFields();
getDerived()->traverseCXXFieldTemplates();
getDerived()->traverseConcepts();
getDerived()->traverseGlobalVariableTemplateRecords();
getDerived()->traverseGlobalVariableTemplateSpecializationRecords();
getDerived()->traverseGlobalVariableTemplatePartialSpecializationRecords();
getDerived()->traverseGlobalFunctionTemplateRecords();
getDerived()->traverseGlobalFunctionTemplateSpecializationRecords();
getDerived()->traverseRecordRecords();
getDerived()->traverseObjCInterfaces();
getDerived()->traverseObjCProtocols();
getDerived()->traverseObjCCategories();
getDerived()->traverseMacroDefinitionRecords();
getDerived()->traverseTypedefRecords();
}
void traverseNamespaces() {
for (const auto &Namespace : API.getNamespaces())
getDerived()->visitNamespaceRecord(*Namespace.second);
}
void traverseGlobalFunctionRecords() {
for (const auto &GlobalFunction : API.getGlobalFunctions())
getDerived()->visitGlobalFunctionRecord(*GlobalFunction.second);
}
void traverseGlobalVariableRecords() {
for (const auto &GlobalVariable : API.getGlobalVariables())
getDerived()->visitGlobalVariableRecord(*GlobalVariable.second);
}
void traverseEnumRecords() {
for (const auto &Enum : API.getEnums())
getDerived()->visitEnumRecord(*Enum.second);
}
void traverseRecordRecords() {
for (const auto &Record : API.getRecords())
getDerived()->visitRecordRecord(*Record.second);
}
void traverseStaticFieldRecords() {
for (const auto &StaticField : API.getStaticFields())
getDerived()->visitStaticFieldRecord(*StaticField.second);
}
void traverseCXXClassRecords() {
for (const auto &Class : API.getCXXClasses())
getDerived()->visitCXXClassRecord(*Class.second);
}
void traverseCXXMethodTemplates() {
for (const auto &MethodTemplate : API.getCXXMethodTemplates())
getDerived()->visitMethodTemplateRecord(*MethodTemplate.second);
}
void traverseCXXMethodTemplateSpecializations() {
for (const auto &MethodTemplateSpecialization :
API.getCXXMethodTemplateSpecializations())
getDerived()->visitMethodTemplateSpecializationRecord(
*MethodTemplateSpecialization.second);
}
void traverseClassTemplateRecords() {
for (const auto &ClassTemplate : API.getClassTemplates())
getDerived()->visitClassTemplateRecord(*ClassTemplate.second);
}
void traverseClassTemplateSpecializationRecords() {
for (const auto &ClassTemplateSpecialization :
API.getClassTemplateSpecializations())
getDerived()->visitClassTemplateSpecializationRecord(
*ClassTemplateSpecialization.second);
}
void traverseClassTemplatePartialSpecializationRecords() {
for (const auto &ClassTemplatePartialSpecialization :
API.getClassTemplatePartialSpecializations())
getDerived()->visitClassTemplatePartialSpecializationRecord(
*ClassTemplatePartialSpecialization.second);
}
void traverseCXXInstanceMethods() {
for (const auto &InstanceMethod : API.getCXXInstanceMethods())
getDerived()->visitCXXInstanceMethodRecord(*InstanceMethod.second);
}
void traverseCXXStaticMethods() {
for (const auto &InstanceMethod : API.getCXXStaticMethods())
getDerived()->visitCXXStaticMethodRecord(*InstanceMethod.second);
}
void traverseCXXFields() {
for (const auto &CXXField : API.getCXXFields())
getDerived()->visitCXXFieldRecord(*CXXField.second);
}
void traverseCXXFieldTemplates() {
for (const auto &CXXFieldTemplate : API.getCXXFieldTemplates())
getDerived()->visitCXXFieldTemplateRecord(*CXXFieldTemplate.second);
}
void traverseGlobalVariableTemplateRecords() {
for (const auto &GlobalVariableTemplate : API.getGlobalVariableTemplates())
getDerived()->visitGlobalVariableTemplateRecord(
*GlobalVariableTemplate.second);
}
void traverseGlobalVariableTemplateSpecializationRecords() {
for (const auto &GlobalVariableTemplateSpecialization :
API.getGlobalVariableTemplateSpecializations())
getDerived()->visitGlobalVariableTemplateSpecializationRecord(
*GlobalVariableTemplateSpecialization.second);
}
void traverseGlobalVariableTemplatePartialSpecializationRecords() {
for (const auto &GlobalVariableTemplatePartialSpecialization :
API.getGlobalVariableTemplatePartialSpecializations())
getDerived()->visitGlobalVariableTemplatePartialSpecializationRecord(
*GlobalVariableTemplatePartialSpecialization.second);
}
void traverseGlobalFunctionTemplateRecords() {
for (const auto &GlobalFunctionTemplate : API.getGlobalFunctionTemplates())
getDerived()->visitGlobalFunctionTemplateRecord(
*GlobalFunctionTemplate.second);
}
void traverseGlobalFunctionTemplateSpecializationRecords() {
for (const auto &GlobalFunctionTemplateSpecialization :
API.getGlobalFunctionTemplateSpecializations())
getDerived()->visitGlobalFunctionTemplateSpecializationRecord(
*GlobalFunctionTemplateSpecialization.second);
}
void traverseConcepts() {
for (const auto &Concept : API.getConcepts())
getDerived()->visitConceptRecord(*Concept.second);
}
void traverseObjCInterfaces() {
for (const auto &Interface : API.getObjCInterfaces())
getDerived()->visitObjCContainerRecord(*Interface.second);
}
void traverseObjCProtocols() {
for (const auto &Protocol : API.getObjCProtocols())
getDerived()->visitObjCContainerRecord(*Protocol.second);
}
void traverseObjCCategories() {
for (const auto &Category : API.getObjCCategories())
getDerived()->visitObjCCategoryRecord(*Category.second);
}
void traverseMacroDefinitionRecords() {
for (const auto &Macro : API.getMacros())
getDerived()->visitMacroDefinitionRecord(*Macro.second);
}
void traverseTypedefRecords() {
for (const auto &Typedef : API.getTypedefs())
getDerived()->visitTypedefRecord(*Typedef.second);
}
void visitNamespaceRecord(const NamespaceRecord &Record){};
/// Visit a global function record.
void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record){};
/// Visit a global variable record.
void visitGlobalVariableRecord(const GlobalVariableRecord &Record){};
/// Visit an enum record.
void visitEnumRecord(const EnumRecord &Record){};
/// Visit a record record.
void visitRecordRecord(const RecordRecord &Record){};
void visitStaticFieldRecord(const StaticFieldRecord &Record){};
void visitCXXClassRecord(const CXXClassRecord &Record){};
void visitClassTemplateRecord(const ClassTemplateRecord &Record){};
void visitClassTemplateSpecializationRecord(
const ClassTemplateSpecializationRecord &Record){};
void visitClassTemplatePartialSpecializationRecord(
const ClassTemplatePartialSpecializationRecord &Record){};
void visitCXXInstanceRecord(const CXXInstanceMethodRecord &Record){};
void visitCXXStaticRecord(const CXXStaticMethodRecord &Record){};
void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record){};
void visitMethodTemplateSpecializationRecord(
const CXXMethodTemplateSpecializationRecord &Record){};
void visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord &Record){};
void visitGlobalVariableTemplateRecord(
const GlobalVariableTemplateRecord &Record) {}
void visitGlobalVariableTemplateSpecializationRecord(
const GlobalVariableTemplateSpecializationRecord &Record){};
void visitGlobalVariableTemplatePartialSpecializationRecord(
const GlobalVariableTemplatePartialSpecializationRecord &Record){};
void visitGlobalFunctionTemplateRecord(
const GlobalFunctionTemplateRecord &Record){};
void visitGlobalFunctionTemplateSpecializationRecord(
const GlobalFunctionTemplateSpecializationRecord &Record){};
/// Visit an Objective-C container record.
void visitObjCContainerRecord(const ObjCContainerRecord &Record){};
/// Visit an Objective-C category record.
void visitObjCCategoryRecord(const ObjCCategoryRecord &Record){};
/// Visit a macro definition record.
void visitMacroDefinitionRecord(const MacroDefinitionRecord &Record){};
/// Visit a typedef record.
void visitTypedefRecord(const TypedefRecord &Record){};
protected:
const APISet &API;
public:
APISetVisitor() = delete;
APISetVisitor(const APISetVisitor &) = delete;
APISetVisitor(APISetVisitor &&) = delete;
APISetVisitor &operator=(const APISetVisitor &) = delete;
APISetVisitor &operator=(APISetVisitor &&) = delete;
protected:
APISetVisitor(const APISet &API) : API(API) {}
~APISetVisitor() = default;
Derived *getDerived() { return static_cast<Derived *>(this); };
};
} // namespace extractapi
} // namespace clang
#endif // LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H

View File

@ -17,17 +17,11 @@
#ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H
#define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H
#include "clang/Basic/Module.h"
#include "clang/ExtractAPI/API.h"
#include "clang/ExtractAPI/APIIgnoresList.h"
#include "clang/ExtractAPI/Serialization/APISetVisitor.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "clang/ExtractAPI/Serialization/SerializerBase.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
@ -41,30 +35,7 @@ using namespace llvm::json;
/// Common options to customize the visitor output.
struct SymbolGraphSerializerOption {
/// Do not include unnecessary whitespaces to save space.
bool Compact = true;
bool EmitSymbolLabelsForTesting = false;
};
/// A representation of the contents of a given module symbol graph
struct ExtendedModule {
ExtendedModule() = default;
ExtendedModule(ExtendedModule &&EM) = default;
ExtendedModule &operator=(ExtendedModule &&EM) = default;
// Copies are expensive so disable them.
ExtendedModule(const ExtendedModule &EM) = delete;
ExtendedModule &operator=(const ExtendedModule &EM) = delete;
/// Add a symbol to the module, do not store the resulting pointer or use it
/// across insertions.
Object *addSymbol(Object &&Symbol);
void addRelationship(Object &&Relationship);
/// A JSON array of formatted symbols from an \c APISet.
Array Symbols;
/// A JSON array of formatted symbol relationships from an \c APISet.
Array Relationships;
bool Compact;
};
/// The visitor that organizes API information in the Symbol Graph format.
@ -73,54 +44,28 @@ struct ExtendedModule {
/// models an API set as a directed graph, where nodes are symbol declarations,
/// and edges are relationships between the connected symbols.
class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> {
private:
using Base = APISetVisitor<SymbolGraphSerializer>;
/// The main symbol graph that contains symbols that are either top-level or a
/// are related to symbols defined in this product/module.
ExtendedModule MainModule;
/// A JSON array of formatted symbols in \c APISet.
Array Symbols;
/// Additional symbol graphs that contain symbols that are related to symbols
/// defined in another product/module. The key of this map is the module name
/// of the extended module.
llvm::StringMap<ExtendedModule> ExtendedModules;
/// A JSON array of formatted symbol relationships in \c APISet.
Array Relationships;
/// The Symbol Graph format version used by this serializer.
static const VersionTuple FormatVersion;
/// Indicates whether to take into account the extended module. This is only
/// Indicates whether child symbols should be visited. This is mainly
/// useful for \c serializeSingleSymbolSGF.
bool ForceEmitToMainModule;
// Stores the references required to construct path components for the
// currently visited APIRecord.
llvm::SmallVector<SymbolReference, 8> Hierarchy;
/// The list of symbols to ignore.
///
/// Note: This should be consulted before emitting a symbol.
const APIIgnoresList &IgnoresList;
const bool EmitSymbolLabelsForTesting = false;
/// The object instantiated by the last call to serializeAPIRecord.
Object *CurrentSymbol = nullptr;
/// The module to which \p CurrentSymbol belongs too.
ExtendedModule *ModuleForCurrentSymbol = nullptr;
bool ShouldRecurse;
public:
static void
serializeMainSymbolGraph(raw_ostream &OS, const APISet &API,
const APIIgnoresList &IgnoresList,
SymbolGraphSerializerOption Options = {});
/// Serialize the APIs in \c APISet in the Symbol Graph format.
///
/// \returns a JSON object that contains the root of the formatted
/// Symbol Graph.
Object serialize();
static void serializeWithExtensionGraphs(
raw_ostream &MainOutput, const APISet &API,
const APIIgnoresList &IgnoresList,
llvm::function_ref<
std::unique_ptr<llvm::raw_pwrite_stream>(llvm::Twine BaseFileName)>
CreateOutputStream,
SymbolGraphSerializerOption Options = {});
/// Wrap serialize(void) and write out the serialized JSON object to \p os.
void serialize(raw_ostream &os);
/// Serialize a single symbol SGF. This is primarily used for libclang.
///
@ -130,7 +75,6 @@ public:
static std::optional<Object> serializeSingleSymbolSGF(StringRef USR,
const APISet &API);
private:
/// The kind of a relationship between two symbols.
enum RelationshipKind {
/// The source symbol is a member of the target symbol.
@ -150,32 +94,16 @@ private:
ExtensionTo,
};
/// Serialize a single record.
void serializeSingleRecord(const APIRecord *Record);
/// Get the string representation of the relationship kind.
static StringRef getRelationshipString(RelationshipKind Kind);
void serializeRelationship(RelationshipKind Kind,
const SymbolReference &Source,
const SymbolReference &Target,
ExtendedModule &Into);
enum ConstraintKind { Conformance, ConditionalConformance };
static StringRef getConstraintString(ConstraintKind Kind);
/// Serialize the APIs in \c ExtendedModule.
///
/// \returns a JSON object that contains the root of the formatted
/// Symbol Graph.
Object serializeGraph(StringRef ModuleName, ExtendedModule &&EM);
/// Serialize the APIs in \c ExtendedModule in the Symbol Graph format and
/// write them to the provide stream.
void serializeGraphToStream(raw_ostream &OS,
SymbolGraphSerializerOption Options,
StringRef ModuleName, ExtendedModule &&EM);
private:
/// Just serialize the currently recorded objects in Symbol Graph format.
Object serializeCurrentGraph();
/// Synthesize the metadata section of the Symbol Graph format.
///
@ -189,92 +117,124 @@ private:
/// by the given API set.
/// Note that "module" here is not to be confused with the Clang/C++ module
/// concept.
Object serializeModuleObject(StringRef ModuleName) const;
Array serializePathComponents(const APIRecord *Record) const;
Object serializeModule() const;
/// Determine if the given \p Record should be skipped during serialization.
bool shouldSkip(const APIRecord *Record) const;
ExtendedModule &getModuleForCurrentSymbol();
bool shouldSkip(const APIRecord &Record) const;
/// Format the common API information for \p Record.
///
/// This handles the shared information of all kinds of API records,
/// for example identifier, source location and path components. The resulting
/// object is then augmented with kind-specific symbol information in
/// subsequent visit* methods by accessing the \p State member variable. This
/// method also checks if the given \p Record should be skipped during
/// serialization. This should be called only once per concrete APIRecord
/// instance and the first visit* method to be called is responsible for
/// calling this. This is normally visitAPIRecord unless a walkUpFromFoo
/// method is implemented along the inheritance hierarchy in which case the
/// visitFoo method needs to call this.
/// for example identifier and source location. The resulting object is then
/// augmented with kind-specific symbol information by the caller.
/// This method also checks if the given \p Record should be skipped during
/// serialization.
///
/// \returns \c nullptr if this \p Record should be skipped, or a pointer to
/// JSON object containing common symbol information of \p Record. Do not
/// store the returned pointer only use it to augment the object with record
/// specific information as it directly points to the object in the
/// \p ExtendedModule, the pointer won't be valid as soon as another object is
/// inserted into the module.
void serializeAPIRecord(const APIRecord *Record);
/// \returns \c std::nullopt if this \p Record should be skipped, or a JSON
/// object containing common symbol information of \p Record.
template <typename RecordTy>
std::optional<Object> serializeAPIRecord(const RecordTy &Record) const;
/// Helper method to serialize second-level member records of \p Record and
/// the member-of relationships.
template <typename MemberTy>
void serializeMembers(const APIRecord &Record,
const SmallVector<std::unique_ptr<MemberTy>> &Members);
/// Serialize the \p Kind relationship between \p Source and \p Target.
///
/// Record the relationship between the two symbols in
/// SymbolGraphSerializer::Relationships.
void serializeRelationship(RelationshipKind Kind, SymbolReference Source,
SymbolReference Target);
protected:
/// The list of symbols to ignore.
///
/// Note: This should be consulted before emitting a symbol.
const APIIgnoresList &IgnoresList;
SymbolGraphSerializerOption Options;
llvm::StringSet<> visitedCategories;
public:
// Handle if records should be skipped at this level of the traversal to
// ensure that children of skipped records aren't serialized.
bool traverseAPIRecord(const APIRecord *Record);
bool visitAPIRecord(const APIRecord *Record);
void visitNamespaceRecord(const NamespaceRecord &Record);
/// Visit a global function record.
bool visitGlobalFunctionRecord(const GlobalFunctionRecord *Record);
void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record);
bool visitCXXClassRecord(const CXXClassRecord *Record);
/// Visit a global variable record.
void visitGlobalVariableRecord(const GlobalVariableRecord &Record);
bool visitClassTemplateRecord(const ClassTemplateRecord *Record);
/// Visit an enum record.
void visitEnumRecord(const EnumRecord &Record);
bool visitClassTemplatePartialSpecializationRecord(
const ClassTemplatePartialSpecializationRecord *Record);
/// Visit a record record.
void visitRecordRecord(const RecordRecord &Record);
bool visitCXXMethodRecord(const CXXMethodRecord *Record);
void visitStaticFieldRecord(const StaticFieldRecord &Record);
bool visitCXXMethodTemplateRecord(const CXXMethodTemplateRecord *Record);
void visitCXXClassRecord(const CXXClassRecord &Record);
bool visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord *Record);
void visitClassTemplateRecord(const ClassTemplateRecord &Record);
bool visitConceptRecord(const ConceptRecord *Record);
void visitClassTemplateSpecializationRecord(
const ClassTemplateSpecializationRecord &Record);
bool
visitGlobalVariableTemplateRecord(const GlobalVariableTemplateRecord *Record);
void visitClassTemplatePartialSpecializationRecord(
const ClassTemplatePartialSpecializationRecord &Record);
bool visitGlobalVariableTemplatePartialSpecializationRecord(
const GlobalVariableTemplatePartialSpecializationRecord *Record);
void visitCXXInstanceMethodRecord(const CXXInstanceMethodRecord &Record);
bool
visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord *Record);
void visitCXXStaticMethodRecord(const CXXStaticMethodRecord &Record);
bool visitObjCContainerRecord(const ObjCContainerRecord *Record);
void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record);
bool visitObjCInterfaceRecord(const ObjCInterfaceRecord *Record);
void visitMethodTemplateSpecializationRecord(
const CXXMethodTemplateSpecializationRecord &Record);
bool traverseObjCCategoryRecord(const ObjCCategoryRecord *Record);
bool walkUpFromObjCCategoryRecord(const ObjCCategoryRecord *Record);
bool visitObjCCategoryRecord(const ObjCCategoryRecord *Record);
void visitCXXFieldRecord(const CXXFieldRecord &Record);
bool visitObjCMethodRecord(const ObjCMethodRecord *Record);
void visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord &Record);
bool
visitObjCInstanceVariableRecord(const ObjCInstanceVariableRecord *Record);
void visitConceptRecord(const ConceptRecord &Record);
bool walkUpFromTypedefRecord(const TypedefRecord *Record);
bool visitTypedefRecord(const TypedefRecord *Record);
void
visitGlobalVariableTemplateRecord(const GlobalVariableTemplateRecord &Record);
void visitGlobalVariableTemplateSpecializationRecord(
const GlobalVariableTemplateSpecializationRecord &Record);
void visitGlobalVariableTemplatePartialSpecializationRecord(
const GlobalVariableTemplatePartialSpecializationRecord &Record);
void
visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord &Record);
void visitGlobalFunctionTemplateSpecializationRecord(
const GlobalFunctionTemplateSpecializationRecord &Record);
/// Visit an Objective-C container record.
void visitObjCContainerRecord(const ObjCContainerRecord &Record);
/// Visit an Objective-C category record.
void visitObjCCategoryRecord(const ObjCCategoryRecord &Record);
/// Visit a macro definition record.
void visitMacroDefinitionRecord(const MacroDefinitionRecord &Record);
/// Visit a typedef record.
void visitTypedefRecord(const TypedefRecord &Record);
/// Serialize a single record.
void serializeSingleRecord(const APIRecord *Record);
SymbolGraphSerializer(const APISet &API, const APIIgnoresList &IgnoresList,
bool EmitSymbolLabelsForTesting = false,
bool ForceEmitToMainModule = false)
: Base(API), ForceEmitToMainModule(ForceEmitToMainModule),
IgnoresList(IgnoresList),
EmitSymbolLabelsForTesting(EmitSymbolLabelsForTesting) {}
SymbolGraphSerializerOption Options = {},
bool ShouldRecurse = true)
: APISetVisitor(API), ShouldRecurse(ShouldRecurse),
IgnoresList(IgnoresList), Options(Options) {}
};
} // namespace extractapi

View File

@ -15,7 +15,6 @@
#include "clang/Sema/CodeCompleteOptions.h"
#include "clang/Serialization/ModuleFileExtension.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cassert>
#include <map>
@ -388,22 +387,6 @@ public:
LLVM_PREFERRED_TYPE(bool)
unsigned ModulesShareFileManager : 1;
/// Whether to emit symbol graph files as a side effect of compilation.
LLVM_PREFERRED_TYPE(bool)
unsigned EmitSymbolGraph : 1;
/// Whether to emit additional symbol graphs for extended modules.
LLVM_PREFERRED_TYPE(bool)
unsigned EmitExtensionSymbolGraphs : 1;
/// Whether to emit symbol labels for testing in generated symbol graphs
LLVM_PREFERRED_TYPE(bool)
unsigned EmitSymbolGraphSymbolLabelsForTesting : 1;
/// Whether to emit symbol labels for testing in generated symbol graphs
LLVM_PREFERRED_TYPE(bool)
unsigned EmitPrettySymbolGraphs : 1;
CodeCompleteOptions CodeCompleteOpts;
/// Specifies the output format of the AST.
@ -513,8 +496,10 @@ public:
// ignore when extracting documentation.
std::vector<std::string> ExtractAPIIgnoresFileList;
// Currently this is only used as part of the `-emit-symbol-graph`
// action.
// Location of output directory where symbol graph information would
// be dumped. This overrides regular -o output file specification
// be dumped
std::string SymbolGraphOutputDir;
/// Args to pass to the plugins

View File

@ -49,7 +49,6 @@
#include "ToolChains/WebAssembly.h"
#include "ToolChains/XCore.h"
#include "ToolChains/ZOS.h"
#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/TargetID.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
@ -5890,12 +5889,6 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
&JA);
}
if (JA.getType() == types::TY_API_INFO &&
C.getArgs().hasArg(options::OPT_emit_extension_symbol_graphs) &&
C.getArgs().hasArg(options::OPT_o))
Diag(clang::diag::err_drv_unexpected_symbol_graph_output)
<< C.getArgs().getLastArgValue(options::OPT_o);
// DXC defaults to standard out when generating assembly. We check this after
// any DXC flags that might specify a file.
if (AtTopLevel && JA.getType() == types::TY_PP_Asm && IsDXCMode())

View File

@ -5037,26 +5037,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
assert(JA.getType() == types::TY_API_INFO &&
"Extract API actions must generate a API information.");
CmdArgs.push_back("-extract-api");
if (Arg *PrettySGFArg = Args.getLastArg(options::OPT_emit_pretty_sgf))
PrettySGFArg->render(Args, CmdArgs);
Arg *SymbolGraphDirArg = Args.getLastArg(options::OPT_symbol_graph_dir_EQ);
if (Arg *ProductNameArg = Args.getLastArg(options::OPT_product_name_EQ))
ProductNameArg->render(Args, CmdArgs);
if (Arg *ExtractAPIIgnoresFileArg =
Args.getLastArg(options::OPT_extract_api_ignores_EQ))
ExtractAPIIgnoresFileArg->render(Args, CmdArgs);
if (Arg *EmitExtensionSymbolGraphs =
Args.getLastArg(options::OPT_emit_extension_symbol_graphs)) {
if (!SymbolGraphDirArg)
D.Diag(diag::err_drv_missing_symbol_graph_dir);
EmitExtensionSymbolGraphs->render(Args, CmdArgs);
}
if (SymbolGraphDirArg)
SymbolGraphDirArg->render(Args, CmdArgs);
} else {
assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) &&
"Invalid action for clang tool.");

View File

@ -13,67 +13,514 @@
//===----------------------------------------------------------------------===//
#include "clang/ExtractAPI/API.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/CommentLexer.h"
#include "clang/AST/RawCommentList.h"
#include "clang/Basic/Module.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorHandling.h"
#include <memory>
using namespace clang::extractapi;
using namespace llvm;
SymbolReference::SymbolReference(const APIRecord *R)
: Name(R->Name), USR(R->USR), Record(R) {}
namespace {
APIRecord *APIRecord::castFromRecordContext(const RecordContext *Ctx) {
switch (Ctx->getKind()) {
#define RECORD_CONTEXT(CLASS, KIND) \
case KIND: \
return static_cast<CLASS *>(const_cast<RecordContext *>(Ctx));
#include "clang/ExtractAPI/APIRecords.inc"
default:
return nullptr;
// llvm_unreachable("RecordContext derived class isn't propertly
// implemented");
}
template <typename RecordTy, typename... CtorArgsTy>
RecordTy *addTopLevelRecord(DenseMap<StringRef, APIRecord *> &USRLookupTable,
APISet::RecordMap<RecordTy> &RecordMap,
StringRef USR, CtorArgsTy &&...CtorArgs) {
auto Result = RecordMap.insert({USR, nullptr});
// Create the record if it does not already exist
if (Result.second)
Result.first->second =
std::make_unique<RecordTy>(USR, std::forward<CtorArgsTy>(CtorArgs)...);
auto *Record = Result.first->second.get();
USRLookupTable.insert({USR, Record});
return Record;
}
RecordContext *APIRecord::castToRecordContext(const APIRecord *Record) {
if (!Record)
return nullptr;
switch (Record->getKind()) {
#define RECORD_CONTEXT(CLASS, KIND) \
case KIND: \
return static_cast<CLASS *>(const_cast<APIRecord *>(Record));
#include "clang/ExtractAPI/APIRecords.inc"
default:
return nullptr;
// llvm_unreachable("RecordContext derived class isn't propertly
// implemented");
}
} // namespace
NamespaceRecord *
APISet::addNamespace(APIRecord *Parent, StringRef Name, StringRef USR,
PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader) {
auto *Record = addTopLevelRecord(
USRBasedLookupTable, Namespaces, USR, Name, Loc, std::move(Availability),
Linkage, Comment, Declaration, SubHeading, IsFromSystemHeader);
if (Parent)
Record->ParentInformation = APIRecord::HierarchyInformation(
Parent->USR, Parent->Name, Parent->getKind(), Parent);
return Record;
}
void RecordContext::addToRecordChain(APIRecord *Record) const {
if (!First) {
First = Record;
Last = Record;
return;
}
GlobalVariableRecord *
APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Fragments,
DeclarationFragments SubHeading, bool IsFromSystemHeader) {
return addTopLevelRecord(USRBasedLookupTable, GlobalVariables, USR, Name, Loc,
std::move(Availability), Linkage, Comment, Fragments,
SubHeading, IsFromSystemHeader);
}
Last->NextInContext = Record;
Last = Record;
GlobalVariableTemplateRecord *APISet::addGlobalVariableTemplate(
StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, Template Template,
bool IsFromSystemHeader) {
return addTopLevelRecord(USRBasedLookupTable, GlobalVariableTemplates, USR,
Name, Loc, std::move(Availability), Linkage, Comment,
Declaration, SubHeading, Template,
IsFromSystemHeader);
}
GlobalFunctionRecord *APISet::addGlobalFunction(
StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Fragments,
DeclarationFragments SubHeading, FunctionSignature Signature,
bool IsFromSystemHeader) {
return addTopLevelRecord(USRBasedLookupTable, GlobalFunctions, USR, Name, Loc,
std::move(Availability), Linkage, Comment, Fragments,
SubHeading, Signature, IsFromSystemHeader);
}
GlobalFunctionTemplateRecord *APISet::addGlobalFunctionTemplate(
StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
Template Template, bool IsFromSystemHeader) {
return addTopLevelRecord(USRBasedLookupTable, GlobalFunctionTemplates, USR,
Name, Loc, std::move(Availability), Linkage, Comment,
Declaration, SubHeading, Signature, Template,
IsFromSystemHeader);
}
GlobalFunctionTemplateSpecializationRecord *
APISet::addGlobalFunctionTemplateSpecialization(
StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
bool IsFromSystemHeader) {
return addTopLevelRecord(
USRBasedLookupTable, GlobalFunctionTemplateSpecializations, USR, Name,
Loc, std::move(Availability), Linkage, Comment, Declaration, SubHeading,
Signature, IsFromSystemHeader);
}
EnumConstantRecord *APISet::addEnumConstant(EnumRecord *Enum, StringRef Name,
StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
bool IsFromSystemHeader) {
auto Record = std::make_unique<EnumConstantRecord>(
USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading,
IsFromSystemHeader);
Record->ParentInformation = APIRecord::HierarchyInformation(
Enum->USR, Enum->Name, Enum->getKind(), Enum);
USRBasedLookupTable.insert({USR, Record.get()});
return Enum->Constants.emplace_back(std::move(Record)).get();
}
EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
bool IsFromSystemHeader) {
return addTopLevelRecord(USRBasedLookupTable, Enums, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, IsFromSystemHeader);
}
RecordFieldRecord *APISet::addRecordField(
RecordRecord *Record, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
APIRecord::RecordKind Kind, bool IsFromSystemHeader) {
auto RecordField = std::make_unique<RecordFieldRecord>(
USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading,
Kind, IsFromSystemHeader);
RecordField->ParentInformation = APIRecord::HierarchyInformation(
Record->USR, Record->Name, Record->getKind(), Record);
USRBasedLookupTable.insert({USR, RecordField.get()});
return Record->Fields.emplace_back(std::move(RecordField)).get();
}
RecordRecord *APISet::addRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
APIRecord::RecordKind Kind,
bool IsFromSystemHeader) {
return addTopLevelRecord(USRBasedLookupTable, Records, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Kind, IsFromSystemHeader);
}
StaticFieldRecord *
APISet::addStaticField(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference Context,
AccessControl Access, bool IsFromSystemHeader) {
return addTopLevelRecord(USRBasedLookupTable, StaticFields, USR, Name, Loc,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, Context, Access,
IsFromSystemHeader);
}
CXXFieldRecord *
APISet::addCXXField(APIRecord *CXXClass, StringRef Name, StringRef USR,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
bool IsFromSystemHeader) {
auto *Record = addTopLevelRecord(
USRBasedLookupTable, CXXFields, USR, Name, Loc, std::move(Availability),
Comment, Declaration, SubHeading, Access, IsFromSystemHeader);
Record->ParentInformation = APIRecord::HierarchyInformation(
CXXClass->USR, CXXClass->Name, CXXClass->getKind(), CXXClass);
return Record;
}
CXXFieldTemplateRecord *APISet::addCXXFieldTemplate(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
AccessControl Access, Template Template, bool IsFromSystemHeader) {
auto *Record =
addTopLevelRecord(USRBasedLookupTable, CXXFieldTemplates, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Access, Template, IsFromSystemHeader);
Record->ParentInformation = APIRecord::HierarchyInformation(
Parent->USR, Parent->Name, Parent->getKind(), Parent);
return Record;
}
CXXClassRecord *
APISet::addCXXClass(APIRecord *Parent, StringRef Name, StringRef USR,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, APIRecord::RecordKind Kind,
AccessControl Access, bool IsFromSystemHeader) {
auto *Record = addTopLevelRecord(
USRBasedLookupTable, CXXClasses, USR, Name, Loc, std::move(Availability),
Comment, Declaration, SubHeading, Kind, Access, IsFromSystemHeader);
if (Parent)
Record->ParentInformation = APIRecord::HierarchyInformation(
Parent->USR, Parent->Name, Parent->getKind(), Parent);
return Record;
}
ClassTemplateRecord *APISet::addClassTemplate(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
Template Template, AccessControl Access, bool IsFromSystemHeader) {
auto *Record =
addTopLevelRecord(USRBasedLookupTable, ClassTemplates, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Template, Access, IsFromSystemHeader);
if (Parent)
Record->ParentInformation = APIRecord::HierarchyInformation(
Parent->USR, Parent->Name, Parent->getKind(), Parent);
return Record;
}
ClassTemplateSpecializationRecord *APISet::addClassTemplateSpecialization(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
AccessControl Access, bool IsFromSystemHeader) {
auto *Record =
addTopLevelRecord(USRBasedLookupTable, ClassTemplateSpecializations, USR,
Name, Loc, std::move(Availability), Comment,
Declaration, SubHeading, Access, IsFromSystemHeader);
if (Parent)
Record->ParentInformation = APIRecord::HierarchyInformation(
Parent->USR, Parent->Name, Parent->getKind(), Parent);
return Record;
}
ClassTemplatePartialSpecializationRecord *
APISet::addClassTemplatePartialSpecialization(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
Template Template, AccessControl Access, bool IsFromSystemHeader) {
auto *Record = addTopLevelRecord(
USRBasedLookupTable, ClassTemplatePartialSpecializations, USR, Name, Loc,
std::move(Availability), Comment, Declaration, SubHeading, Template,
Access, IsFromSystemHeader);
if (Parent)
Record->ParentInformation = APIRecord::HierarchyInformation(
Parent->USR, Parent->Name, Parent->getKind(), Parent);
return Record;
}
GlobalVariableTemplateSpecializationRecord *
APISet::addGlobalVariableTemplateSpecialization(
StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader) {
return addTopLevelRecord(USRBasedLookupTable,
GlobalVariableTemplateSpecializations, USR, Name,
Loc, std::move(Availability), Linkage, Comment,
Declaration, SubHeading, IsFromSystemHeader);
}
GlobalVariableTemplatePartialSpecializationRecord *
APISet::addGlobalVariableTemplatePartialSpecialization(
StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, Template Template,
bool IsFromSystemHeader) {
return addTopLevelRecord(
USRBasedLookupTable, GlobalVariableTemplatePartialSpecializations, USR,
Name, Loc, std::move(Availability), Linkage, Comment, Declaration,
SubHeading, Template, IsFromSystemHeader);
}
ConceptRecord *APISet::addConcept(StringRef Name, StringRef USR,
PresumedLoc Loc,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
Template Template, bool IsFromSystemHeader) {
return addTopLevelRecord(USRBasedLookupTable, Concepts, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Template, IsFromSystemHeader);
}
CXXMethodRecord *APISet::addCXXInstanceMethod(
APIRecord *CXXClassRecord, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader) {
CXXMethodRecord *Record =
addTopLevelRecord(USRBasedLookupTable, CXXInstanceMethods, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, Access, IsFromSystemHeader);
Record->ParentInformation = APIRecord::HierarchyInformation(
CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(),
CXXClassRecord);
return Record;
}
CXXMethodRecord *APISet::addCXXStaticMethod(
APIRecord *CXXClassRecord, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader) {
CXXMethodRecord *Record =
addTopLevelRecord(USRBasedLookupTable, CXXStaticMethods, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, Access, IsFromSystemHeader);
Record->ParentInformation = APIRecord::HierarchyInformation(
CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(),
CXXClassRecord);
return Record;
}
CXXMethodTemplateRecord *APISet::addCXXMethodTemplate(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access, Template Template,
bool IsFromSystemHeader) {
auto *Record = addTopLevelRecord(USRBasedLookupTable, CXXMethodTemplates, USR,
Name, Loc, std::move(Availability), Comment,
Declaration, SubHeading, Signature, Access,
Template, IsFromSystemHeader);
Record->ParentInformation = APIRecord::HierarchyInformation(
Parent->USR, Parent->Name, Parent->getKind(), Parent);
return Record;
}
CXXMethodTemplateSpecializationRecord *APISet::addCXXMethodTemplateSpec(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader) {
auto *Record = addTopLevelRecord(
USRBasedLookupTable, CXXMethodTemplateSpecializations, USR, Name, Loc,
std::move(Availability), Comment, Declaration, SubHeading, Signature,
Access, IsFromSystemHeader);
Record->ParentInformation = APIRecord::HierarchyInformation(
Parent->USR, Parent->Name, Parent->getKind(), Parent);
return Record;
}
ObjCCategoryRecord *APISet::addObjCCategory(
StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
SymbolReference Interface, bool IsFromSystemHeader,
bool IsFromExternalModule) {
// Create the category record.
auto *Record =
addTopLevelRecord(USRBasedLookupTable, ObjCCategories, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Interface, IsFromSystemHeader);
Record->IsFromExternalModule = IsFromExternalModule;
auto It = ObjCInterfaces.find(Interface.USR);
if (It != ObjCInterfaces.end())
It->second->Categories.push_back(Record);
return Record;
}
ObjCInterfaceRecord *
APISet::addObjCInterface(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
SymbolReference SuperClass, bool IsFromSystemHeader) {
return addTopLevelRecord(USRBasedLookupTable, ObjCInterfaces, USR, Name, Loc,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, SuperClass,
IsFromSystemHeader);
}
ObjCMethodRecord *APISet::addObjCMethod(
ObjCContainerRecord *Container, StringRef Name, StringRef USR,
PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsInstanceMethod,
bool IsFromSystemHeader) {
std::unique_ptr<ObjCMethodRecord> Record;
if (IsInstanceMethod)
Record = std::make_unique<ObjCInstanceMethodRecord>(
USR, Name, Loc, std::move(Availability), Comment, Declaration,
SubHeading, Signature, IsFromSystemHeader);
else
Record = std::make_unique<ObjCClassMethodRecord>(
USR, Name, Loc, std::move(Availability), Comment, Declaration,
SubHeading, Signature, IsFromSystemHeader);
Record->ParentInformation = APIRecord::HierarchyInformation(
Container->USR, Container->Name, Container->getKind(), Container);
USRBasedLookupTable.insert({USR, Record.get()});
return Container->Methods.emplace_back(std::move(Record)).get();
}
ObjCPropertyRecord *APISet::addObjCProperty(
ObjCContainerRecord *Container, StringRef Name, StringRef USR,
PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
ObjCPropertyRecord::AttributeKind Attributes, StringRef GetterName,
StringRef SetterName, bool IsOptional, bool IsInstanceProperty,
bool IsFromSystemHeader) {
std::unique_ptr<ObjCPropertyRecord> Record;
if (IsInstanceProperty)
Record = std::make_unique<ObjCInstancePropertyRecord>(
USR, Name, Loc, std::move(Availability), Comment, Declaration,
SubHeading, Attributes, GetterName, SetterName, IsOptional,
IsFromSystemHeader);
else
Record = std::make_unique<ObjCClassPropertyRecord>(
USR, Name, Loc, std::move(Availability), Comment, Declaration,
SubHeading, Attributes, GetterName, SetterName, IsOptional,
IsFromSystemHeader);
Record->ParentInformation = APIRecord::HierarchyInformation(
Container->USR, Container->Name, Container->getKind(), Container);
USRBasedLookupTable.insert({USR, Record.get()});
return Container->Properties.emplace_back(std::move(Record)).get();
}
ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable(
ObjCContainerRecord *Container, StringRef Name, StringRef USR,
PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
ObjCInstanceVariableRecord::AccessControl Access, bool IsFromSystemHeader) {
auto Record = std::make_unique<ObjCInstanceVariableRecord>(
USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading,
Access, IsFromSystemHeader);
Record->ParentInformation = APIRecord::HierarchyInformation(
Container->USR, Container->Name, Container->getKind(), Container);
USRBasedLookupTable.insert({USR, Record.get()});
return Container->Ivars.emplace_back(std::move(Record)).get();
}
ObjCProtocolRecord *APISet::addObjCProtocol(StringRef Name, StringRef USR,
PresumedLoc Loc,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
bool IsFromSystemHeader) {
return addTopLevelRecord(USRBasedLookupTable, ObjCProtocols, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, IsFromSystemHeader);
}
MacroDefinitionRecord *
APISet::addMacroDefinition(StringRef Name, StringRef USR, PresumedLoc Loc,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
bool IsFromSystemHeader) {
return addTopLevelRecord(USRBasedLookupTable, Macros, USR, Name, Loc,
Declaration, SubHeading, IsFromSystemHeader);
}
TypedefRecord *
APISet::addTypedef(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
SymbolReference UnderlyingType, bool IsFromSystemHeader) {
return addTopLevelRecord(USRBasedLookupTable, Typedefs, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, UnderlyingType, IsFromSystemHeader);
}
APIRecord *APISet::findRecordForUSR(StringRef USR) const {
if (USR.empty())
return nullptr;
auto FindIt = USRBasedLookupTable.find(USR);
if (FindIt != USRBasedLookupTable.end())
return FindIt->getSecond().get();
return USRBasedLookupTable.lookup(USR);
}
return nullptr;
StringRef APISet::recordUSR(const Decl *D) {
SmallString<128> USR;
index::generateUSRForDecl(D, USR);
return copyString(USR);
}
StringRef APISet::recordUSRForMacro(StringRef Name, SourceLocation SL,
const SourceManager &SM) {
SmallString<128> USR;
index::generateUSRForMacro(Name, SL, SM, USR);
return copyString(USR);
}
StringRef APISet::copyString(StringRef String) {
@ -81,22 +528,15 @@ StringRef APISet::copyString(StringRef String) {
return {};
// No need to allocate memory and copy if the string has already been stored.
if (Allocator.identifyObject(String.data()))
if (StringAllocator.identifyObject(String.data()))
return String;
void *Ptr = Allocator.Allocate(String.size(), 1);
void *Ptr = StringAllocator.Allocate(String.size(), 1);
memcpy(Ptr, String.data(), String.size());
return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
}
SymbolReference APISet::createSymbolReference(StringRef Name, StringRef USR,
StringRef Source) {
return SymbolReference(copyString(Name), copyString(USR), copyString(Source));
}
APIRecord::~APIRecord() {}
RecordRecord::~RecordRecord() {}
RecordFieldRecord::~RecordFieldRecord() {}
ObjCContainerRecord::~ObjCContainerRecord() {}
ObjCMethodRecord::~ObjCMethodRecord() {}
ObjCPropertyRecord::~ObjCPropertyRecord() {}
@ -106,10 +546,8 @@ void GlobalFunctionRecord::anchor() {}
void GlobalVariableRecord::anchor() {}
void EnumConstantRecord::anchor() {}
void EnumRecord::anchor() {}
void StructFieldRecord::anchor() {}
void StructRecord::anchor() {}
void UnionFieldRecord::anchor() {}
void UnionRecord::anchor() {}
void RecordFieldRecord::anchor() {}
void RecordRecord::anchor() {}
void CXXFieldRecord::anchor() {}
void CXXClassRecord::anchor() {}
void CXXConstructorRecord::anchor() {}

View File

@ -60,44 +60,23 @@ void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,
} // namespace
DeclarationFragments &
DeclarationFragments::appendUnduplicatedTextCharacter(char Character) {
DeclarationFragments &DeclarationFragments::appendSpace() {
if (!Fragments.empty()) {
Fragment &Last = Fragments.back();
if (Last.Kind == FragmentKind::Text) {
// Merge the extra space into the last fragment if the last fragment is
// also text.
if (Last.Spelling.back() != Character) { // avoid duplicates at end
Last.Spelling.push_back(Character);
if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces.
Last.Spelling.push_back(' ');
}
} else {
append("", FragmentKind::Text);
Fragments.back().Spelling.push_back(Character);
append(" ", FragmentKind::Text);
}
}
return *this;
}
DeclarationFragments &DeclarationFragments::appendSpace() {
return appendUnduplicatedTextCharacter(' ');
}
DeclarationFragments &DeclarationFragments::appendSemicolon() {
return appendUnduplicatedTextCharacter(';');
}
DeclarationFragments &DeclarationFragments::removeTrailingSemicolon() {
if (Fragments.empty())
return *this;
Fragment &Last = Fragments.back();
if (Last.Kind == FragmentKind::Text && Last.Spelling.back() == ';')
Last.Spelling.pop_back();
return *this;
}
StringRef DeclarationFragments::getFragmentKindString(
DeclarationFragments::FragmentKind Kind) {
switch (Kind) {
@ -490,7 +469,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace(
if (!Decl->isAnonymousNamespace())
Fragments.appendSpace().append(
Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
return Fragments.appendSemicolon();
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@ -532,7 +511,7 @@ DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
return Fragments
.append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
.appendSemicolon();
.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@ -564,7 +543,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {
Fragments.append(std::move(ArgumentFragment))
.appendSpace()
.append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
.appendSemicolon();
.append(";", DeclarationFragments::FragmentKind::Text);
return Fragments;
}
@ -733,7 +712,7 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Func->getExceptionSpecType()));
return Fragments.appendSemicolon();
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(
@ -762,7 +741,7 @@ DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
.append(std::move(After));
return Fragments.appendSemicolon();
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@ -778,7 +757,7 @@ DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
.appendSpace()
.append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
.appendSemicolon();
.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
@ -796,7 +775,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
Fragments.appendSpace().append(
Record->getName(), DeclarationFragments::FragmentKind::Identifier);
return Fragments.appendSemicolon();
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
@ -811,7 +790,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
Fragments.appendSpace().append(
Record->getName(), DeclarationFragments::FragmentKind::Identifier);
return Fragments.appendSemicolon();
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@ -841,7 +820,7 @@ DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));
return Fragments.appendSemicolon();
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
@ -881,7 +860,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));
return Fragments.appendSemicolon();
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@ -912,7 +891,7 @@ DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
Fragments.appendSpace().append("const",
DeclarationFragments::FragmentKind::Keyword);
return Fragments.appendSemicolon();
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@ -944,7 +923,7 @@ DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));
return Fragments.appendSemicolon();
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
// Get fragments for template parameters, e.g. T in tempalte<typename T> ...
@ -1049,7 +1028,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(
.appendSpace()
.append(Concept->getName().str(),
DeclarationFragments::FragmentKind::Identifier)
.appendSemicolon();
.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@ -1090,7 +1069,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
Decl->getASTContext(), std::nullopt))
.append(">", DeclarationFragments::FragmentKind::Text)
.appendSemicolon();
.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@ -1112,7 +1091,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(
Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
Decl->getTemplateParameters()->asArray()))
.append(">", DeclarationFragments::FragmentKind::Text)
.appendSemicolon();
.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@ -1131,7 +1110,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
Decl->getASTContext(), std::nullopt))
.append(">", DeclarationFragments::FragmentKind::Text)
.appendSemicolon();
.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@ -1153,7 +1132,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(
Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
Decl->getTemplateParameters()->asArray()))
.append(">", DeclarationFragments::FragmentKind::Text)
.appendSemicolon();
.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@ -1224,7 +1203,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(
Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
.appendSpace()
.append(Interface->getName(),
.append(Category->getClassInterface()->getName(),
DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR,
Interface)
.append(" (", DeclarationFragments::FragmentKind::Text)
@ -1298,7 +1277,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
Fragments.append(getFragmentsForParam(Param));
}
return Fragments.appendSemicolon();
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
@ -1399,7 +1378,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
.append(Property->getName(),
DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
.appendSemicolon();
.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
@ -1443,7 +1422,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
.appendSpace()
.append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
return Fragments.appendSemicolon();
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
// Instantiate template for FunctionDecl.

View File

@ -30,7 +30,6 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/MultiplexConsumer.h"
#include "clang/Index/USRGeneration.h"
#include "clang/InstallAPI/HeaderFile.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/PPCallbacks.h"
@ -40,7 +39,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
@ -329,12 +327,11 @@ public:
StringRef Name = PM.MacroNameToken.getIdentifierInfo()->getName();
PresumedLoc Loc = SM.getPresumedLoc(PM.MacroNameToken.getLocation());
SmallString<128> USR;
index::generateUSRForMacro(Name, PM.MacroNameToken.getLocation(), SM,
USR);
StringRef USR =
API.recordUSRForMacro(Name, PM.MacroNameToken.getLocation(), SM);
API.createRecord<extractapi::MacroDefinitionRecord>(
USR, Name, SymbolReference(), Loc,
API.addMacroDefinition(
Name, USR, Loc,
DeclarationFragmentsBuilder::getFragmentsForMacro(Name, PM.MD),
DeclarationFragmentsBuilder::getSubHeadingForMacro(Name),
SM.isInSystemHeader(PM.MacroNameToken.getLocation()));
@ -375,57 +372,40 @@ private:
LocationFileChecker &LCF;
};
std::unique_ptr<llvm::raw_pwrite_stream>
createAdditionalSymbolGraphFile(CompilerInstance &CI, Twine BaseName) {
auto OutputDirectory = CI.getFrontendOpts().SymbolGraphOutputDir;
SmallString<256> FileName;
llvm::sys::path::append(FileName, OutputDirectory,
BaseName + ".symbols.json");
return CI.createOutputFile(
FileName, /*Binary*/ false, /*RemoveFileOnSignal*/ false,
/*UseTemporary*/ true, /*CreateMissingDirectories*/ true);
}
} // namespace
void ExtractAPIActionBase::ImplEndSourceFileAction(CompilerInstance &CI) {
SymbolGraphSerializerOption SerializationOptions;
SerializationOptions.Compact = !CI.getFrontendOpts().EmitPrettySymbolGraphs;
SerializationOptions.EmitSymbolLabelsForTesting =
CI.getFrontendOpts().EmitSymbolGraphSymbolLabelsForTesting;
void ExtractAPIActionBase::ImplEndSourceFileAction() {
if (!OS)
return;
if (CI.getFrontendOpts().EmitExtensionSymbolGraphs) {
auto ConstructOutputFile = [&CI](Twine BaseName) {
return createAdditionalSymbolGraphFile(CI, BaseName);
};
SymbolGraphSerializer::serializeWithExtensionGraphs(
*OS, *API, IgnoresList, ConstructOutputFile, SerializationOptions);
} else {
SymbolGraphSerializer::serializeMainSymbolGraph(*OS, *API, IgnoresList,
SerializationOptions);
}
// Flush the stream and close the main output stream.
// Setup a SymbolGraphSerializer to write out collected API information in
// the Symbol Graph format.
// FIXME: Make the kind of APISerializer configurable.
SymbolGraphSerializer SGSerializer(*API, IgnoresList);
SGSerializer.serialize(*OS);
OS.reset();
}
std::unique_ptr<raw_pwrite_stream>
ExtractAPIAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) {
std::unique_ptr<raw_pwrite_stream> OS;
OS = CI.createDefaultOutputFile(/*Binary=*/false, InFile,
/*Extension=*/"json",
/*RemoveFileOnSignal=*/false);
if (!OS)
return nullptr;
return OS;
}
std::unique_ptr<ASTConsumer>
ExtractAPIAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
auto ProductName = CI.getFrontendOpts().ProductName;
if (CI.getFrontendOpts().SymbolGraphOutputDir.empty())
OS = CI.createDefaultOutputFile(/*Binary*/ false, InFile,
/*Extension*/ "symbols.json",
/*RemoveFileOnSignal*/ false,
/*CreateMissingDirectories*/ true);
else
OS = createAdditionalSymbolGraphFile(CI, ProductName);
OS = CreateOutputFile(CI, InFile);
if (!OS)
return nullptr;
auto ProductName = CI.getFrontendOpts().ProductName;
// Now that we have enough information about the language options and the
// target triple, let's create the APISet before anyone uses it.
API = std::make_unique<APISet>(
@ -515,9 +495,7 @@ bool ExtractAPIAction::PrepareToExecuteAction(CompilerInstance &CI) {
return true;
}
void ExtractAPIAction::EndSourceFileAction() {
ImplEndSourceFileAction(getCompilerInstance());
}
void ExtractAPIAction::EndSourceFileAction() { ImplEndSourceFileAction(); }
std::unique_ptr<ASTConsumer>
WrappingExtractAPIAction::CreateASTConsumer(CompilerInstance &CI,
@ -528,9 +506,11 @@ WrappingExtractAPIAction::CreateASTConsumer(CompilerInstance &CI,
CreatedASTConsumer = true;
ProductName = CI.getFrontendOpts().ProductName;
auto InputFilename = llvm::sys::path::filename(InFile);
OS = createAdditionalSymbolGraphFile(CI, InputFilename);
OS = CreateOutputFile(CI, InFile);
if (!OS)
return nullptr;
auto ProductName = CI.getFrontendOpts().ProductName;
// Now that we have enough information about the language options and the
// target triple, let's create the APISet before anyone uses it.
@ -572,6 +552,32 @@ void WrappingExtractAPIAction::EndSourceFileAction() {
WrapperFrontendAction::EndSourceFileAction();
if (CreatedASTConsumer) {
ImplEndSourceFileAction(getCompilerInstance());
ImplEndSourceFileAction();
}
}
std::unique_ptr<raw_pwrite_stream>
WrappingExtractAPIAction::CreateOutputFile(CompilerInstance &CI,
StringRef InFile) {
std::unique_ptr<raw_pwrite_stream> OS;
std::string OutputDir = CI.getFrontendOpts().SymbolGraphOutputDir;
// The symbol graphs need to be generated as a side effect of regular
// compilation so the output should be dumped in the directory provided with
// the command line option.
llvm::SmallString<128> OutFilePath(OutputDir);
auto Seperator = llvm::sys::path::get_separator();
auto Infilename = llvm::sys::path::filename(InFile);
OutFilePath.append({Seperator, Infilename});
llvm::sys::path::replace_extension(OutFilePath, "json");
// StringRef outputFilePathref = *OutFilePath;
// don't use the default output file
OS = CI.createOutputFile(/*OutputPath=*/OutFilePath, /*Binary=*/false,
/*RemoveFileOnSignal=*/true,
/*UseTemporary=*/true,
/*CreateMissingDirectories=*/true);
if (!OS)
return nullptr;
return OS;
}

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
#include "clang/Basic/Module.h"
#include "clang/Index/USRGeneration.h"
using namespace clang;
@ -51,20 +50,17 @@ TypedefUnderlyingTypeResolver::getSymbolReferenceForType(QualType Type,
SmallString<128> TypeUSR;
const NamedDecl *TypeDecl = getUnderlyingTypeDecl(Type);
const TypedefType *TypedefTy = Type->getAs<TypedefType>();
StringRef OwningModuleName;
if (TypeDecl) {
if (!TypedefTy)
TypeName = TypeDecl->getName().str();
clang::index::generateUSRForDecl(TypeDecl, TypeUSR);
if (auto *OwningModule = TypeDecl->getImportedOwningModule())
OwningModuleName = OwningModule->Name;
} else {
clang::index::generateUSRForType(Type, Context, TypeUSR);
}
return API.createSymbolReference(TypeName, TypeUSR, OwningModuleName);
return {API.copyString(TypeName), API.copyString(TypeUSR)};
}
std::string TypedefUnderlyingTypeResolver::getUSRForType(QualType Type) const {

View File

@ -181,13 +181,9 @@ CreateFrontendAction(CompilerInstance &CI) {
#endif
// Wrap the base FE action in an extract api action to generate
// symbol graph as a biproduct of compilation (enabled with
// --emit-symbol-graph option)
if (FEOpts.EmitSymbolGraph) {
if (FEOpts.SymbolGraphOutputDir.empty()) {
CI.getDiagnostics().Report(diag::warn_missing_symbol_graph_dir);
CI.getFrontendOpts().SymbolGraphOutputDir = ".";
}
// symbol graph as a biproduct of compilation ( enabled with
// --emit-symbol-graph option )
if (!FEOpts.SymbolGraphOutputDir.empty()) {
CI.getCodeGenOpts().ClearASTBeforeBackend = false;
Act = std::make_unique<WrappingExtractAPIAction>(std::move(Act));
}

View File

@ -1,9 +1,8 @@
// XFAIL: *
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf --product-name=Availability -triple arm64-apple-macosx -x c-header %t/input.h -o %t/output.json -verify
// RUN: %clang_cc1 -extract-api --product-name=Availability -triple arm64-apple-macosx -x c-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang -extract-api --pretty-sgf -target arm64-apple-macosx \
// RUN: %clang -extract-api -target arm64-apple-macosx \
// RUN: %t/input.h -o %t/output.json
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
@ -15,7 +15,7 @@ template<typename X, typename Y> class Foo {};
template<typename Z> class Foo<Z, int> {};
// expected-no-diagnostics
/// expected-no-diagnostics
//--- reference.output.json.in
{

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -std=c++20 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -std=c++20 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
@ -137,7 +137,7 @@ class Foo {
"precise": "c:@S@Foo@F@Foo#"
},
"kind": {
"displayName": "Constructor",
"displayName": "Instance Method",
"identifier": "c++.method"
},
"location": {
@ -193,7 +193,7 @@ class Foo {
"precise": "c:@S@Foo@F@~Foo#"
},
"kind": {
"displayName": "Destructor",
"displayName": "Instance Method",
"identifier": "c++.method"
},
"location": {

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -5,19 +5,18 @@
// RUN: %t/reference.main.json.in >> %t/reference.main.json
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.test.json.in >> %t/reference.test.json
// RUN: %clang_cc1 %t/test.c %t/main.c -emit-symbol-graph --pretty-sgf \
// RUN: --symbol-graph-dir=%t/SymbolGraphs --product-name=multifile_test -triple=x86_64-apple-macosx12.0.0
// RUN: %clang_cc1 %t/test.c %t/main.c --emit-symbol-graph=%t/SymbolGraphs --product-name=multifile_test -triple=x86_64-apple-macosx12.0.0
// Test main.json
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
// RUN: %t/SymbolGraphs/main.c.symbols.json > %t/output-normalized.json
// RUN: %t/SymbolGraphs/main.json > %t/output-normalized.json
// RUN: diff %t/reference.main.json %t/output-normalized.json
// Test test.json
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
// RUN: %t/SymbolGraphs/test.c.symbols.json > %t/output-normalized.json
// RUN: %t/SymbolGraphs/test.json > %t/output-normalized.json
// RUN: diff %t/reference.test.json %t/output-normalized.json
// CHECK-NOT: error:

View File

@ -3,12 +3,11 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 %t/main.c -emit-symbol-graph --pretty-sgf \
// RUN: --symbol-graph-dir=%t/SymbolGraphs --product-name=basicfile -triple=x86_64-apple-macosx12.0.0
// RUN: %clang_cc1 %t/main.c --emit-symbol-graph=%t/SymbolGraphs --product-name=basicfile -triple=x86_64-apple-macosx12.0.0
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
// RUN: %t/SymbolGraphs/main.c.symbols.json >> %t/output-normalized.json
// RUN: %t/SymbolGraphs/main.json >> %t/output-normalized.json
// RUN: diff %t/reference.output.json %t/output-normalized.json
// CHECK-NOT: error:

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang -extract-api --pretty-sgf --product-name=GlobalRecord -target arm64-apple-macosx \
// RUN: %clang -extract-api --product-name=GlobalRecord -target arm64-apple-macosx \
// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang -extract-api --pretty-sgf --product-name=GlobalRecord -target arm64-apple-macosx \
// RUN: %clang -extract-api --product-name=GlobalRecord -target arm64-apple-macosx \
// RUN: %t/input1.h %t/input2.h %t/input3.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -1,7 +1,17 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: %clang_cc1 -extract-api --pretty-sgf --product-name=GlobalRecord -triple arm64-apple-macosx \
// RUN: %t/input1.h -verify -o - | FileCheck %s
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang -extract-api --product-name=GlobalRecord -target arm64-apple-macosx \
// RUN: %t/input1.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
// RUN: %t/output.json >> %t/output-normalized.json
// RUN: diff %t/reference.output.json %t/output-normalized.json
// CHECK-NOT: error:
// CHECK-NOT: warning:
//--- input1.h
int num;
@ -14,6 +24,87 @@ char not_emitted;
void foo(int);
struct Foo { int a; };
// CHECK-NOT: input2.h
// expected-no-diagnostics
//--- reference.output.json.in
{
"metadata": {
"formatVersion": {
"major": 0,
"minor": 5,
"patch": 3
},
"generator": "?"
},
"module": {
"name": "GlobalRecord",
"platform": {
"architecture": "arm64",
"operatingSystem": {
"minimumVersion": {
"major": 11,
"minor": 0,
"patch": 0
},
"name": "macosx"
},
"vendor": "apple"
}
},
"relationships": [],
"symbols": [
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "num"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:@num"
},
"kind": {
"displayName": "Global Variable",
"identifier": "c.var"
},
"location": {
"position": {
"character": 4,
"line": 0
},
"uri": "file://INPUT_DIR/input1.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "num"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "num"
}
],
"title": "num"
},
"pathComponents": [
"num"
]
}
]
}

View File

@ -7,11 +7,11 @@
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/objcpp.reference.output.json.in >> %t/objcpp.reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -x c-header -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -x c-header -triple arm64-apple-macosx \
// RUN: %t/c.h -o %t/c.output.json | FileCheck -allow-empty %s
// RUN: %clang_cc1 -extract-api --pretty-sgf -x objective-c-header -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -x objective-c-header -triple arm64-apple-macosx \
// RUN: %t/objc.h -o %t/objc.output.json | FileCheck -allow-empty %s
// RUN: %clang_cc1 -extract-api --pretty-sgf -x objective-c++-header -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -x objective-c++-header -triple arm64-apple-macosx \
// RUN: %t/objcpp.h -o %t/objcpp.output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang -extract-api --pretty-sgf --product-name=Macros -target arm64-apple-macosx \
// RUN: %clang -extract-api --product-name=Macros -target arm64-apple-macosx \
// RUN: -x objective-c-header %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang -extract-api --pretty-sgf --product-name=Macros -target arm64-apple-macosx \
// RUN: %clang -extract-api --product-name=Macros -target arm64-apple-macosx \
// RUN: -x objective-c-header %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.

View File

@ -1,32 +0,0 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -extract-api --pretty-sgf --product-name=module -triple arm64-apple-macosx -x c-header %s -o %t/module.symbols.json -verify
// RUN: FileCheck %s --input-file %t/module.symbols.json --check-prefix METADATA
// RUN: FileCheck %s --input-file %t/module.symbols.json --check-prefix MOD
// expected-no-diagnostics
// METADATA: "metadata": {
// METADATA-NEXT: "formatVersion": {
// METADATA-NEXT: "major":
// METADATA-NEXT: "minor":
// METADATA-NEXT: "patch":
// METADATA-NEXT: },
// METADATA-NEXT: "generator":
// METADATA-NEXT: }
// MOD: "module": {
// MOD-NEXT: "name": "module",
// MOD-NEXT: "platform": {
// MOD-NEXT: "architecture": "arm64",
// MOD-NEXT: "operatingSystem": {
// MOD-NEXT: "minimumVersion": {
// MOD-NEXT: "major":
// MOD-NEXT: "minor":
// MOD-NEXT: "patch":
// MOD-NEXT: },
// MOD-NEXT: "name": "macosx"
// MOD-NEXT: },
// MOD-NEXT: "vendor": "apple"
// MOD-NEXT: }
// MOD-NEXT: }

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -1,221 +1,467 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
// RUN: -triple arm64-apple-macosx -x c++-header %s -o %t/output.symbols.json -verify
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
// RUN: %t/output.json >> %t/output-normalized.json
// RUN: diff %t/reference.output.json %t/output-normalized.json
//--- input.h
class Foo {
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GETCOUNT
int getCount();
// GETCOUNT: "!testRelLabel": "memberOf $ c:@S@Foo@F@getCount# $ c:@S@Foo"
// GETCOUNT-LABEL: "!testLabel": "c:@S@Foo@F@getCount#"
// GETCOUNT: "accessLevel": "private",
// GETCOUNT: "declarationFragments": [
// GETCOUNT-NEXT: {
// GETCOUNT-NEXT: "kind": "typeIdentifier",
// GETCOUNT-NEXT: "preciseIdentifier": "c:I",
// GETCOUNT-NEXT: "spelling": "int"
// GETCOUNT-NEXT: },
// GETCOUNT-NEXT: {
// GETCOUNT-NEXT: "kind": "text",
// GETCOUNT-NEXT: "spelling": " "
// GETCOUNT-NEXT: },
// GETCOUNT-NEXT: {
// GETCOUNT-NEXT: "kind": "identifier",
// GETCOUNT-NEXT: "spelling": "getCount"
// GETCOUNT-NEXT: },
// GETCOUNT-NEXT: {
// GETCOUNT-NEXT: "kind": "text",
// GETCOUNT-NEXT: "spelling": "();"
// GETCOUNT-NEXT: }
// GETCOUNT-NEXT: ],
// GETCOUNT: "functionSignature": {
// GETCOUNT-NEXT: "returns": [
// GETCOUNT-NEXT: {
// GETCOUNT-NEXT: "kind": "typeIdentifier",
// GETCOUNT-NEXT: "preciseIdentifier": "c:I",
// GETCOUNT-NEXT: "spelling": "int"
// GETCOUNT-NEXT: }
// GETCOUNT-NEXT: ]
// GETCOUNT-NEXT: },
// GETCOUNT: "displayName": "Instance Method",
// GETCOUNT-NEXT: "identifier": "c++.method"
// GETCOUNT: "title": "getCount"
// GETCOUNT: "pathComponents": [
// GETCOUNT-NEXT: "Foo",
// GETCOUNT-NEXT: "getCount"
// GETCOUNT-NEXT: ]
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix SETL
void setLength(int length) noexcept;
// SETL: "!testRelLabel": "memberOf $ c:@S@Foo@F@setLength#I# $ c:@S@Foo"
// SETL-LABEL: "!testLabel": "c:@S@Foo@F@setLength#I#"
// SETL: "declarationFragments": [
// SETL-NEXT: {
// SETL-NEXT: "kind": "typeIdentifier",
// SETL-NEXT: "preciseIdentifier": "c:v",
// SETL-NEXT: "spelling": "void"
// SETL-NEXT: },
// SETL-NEXT: {
// SETL-NEXT: "kind": "text",
// SETL-NEXT: "spelling": " "
// SETL-NEXT: },
// SETL-NEXT: {
// SETL-NEXT: "kind": "identifier",
// SETL-NEXT: "spelling": "setLength"
// SETL-NEXT: },
// SETL-NEXT: {
// SETL-NEXT: "kind": "text",
// SETL-NEXT: "spelling": "("
// SETL-NEXT: },
// SETL-NEXT: {
// SETL-NEXT: "kind": "typeIdentifier",
// SETL-NEXT: "preciseIdentifier": "c:I",
// SETL-NEXT: "spelling": "int"
// SETL-NEXT: },
// SETL-NEXT: {
// SETL-NEXT: "kind": "text",
// SETL-NEXT: "spelling": " "
// SETL-NEXT: },
// SETL-NEXT: {
// SETL-NEXT: "kind": "internalParam",
// SETL-NEXT: "spelling": "length"
// SETL-NEXT: },
// SETL-NEXT: {
// SETL-NEXT: "kind": "text",
// SETL-NEXT: "spelling": ")"
// SETL-NEXT: },
// SETL-NEXT: {
// SETL-NEXT: "kind": "text",
// SETL-NEXT: "spelling": " "
// SETL-NEXT: },
// SETL-NEXT: {
// SETL-NEXT: "kind": "keyword",
// SETL-NEXT: "spelling": "noexcept"
// SETL-NEXT: },
// SETL-NEXT: {
// SETL-NEXT: "kind": "text",
// SETL-NEXT: "spelling": ";"
// SETL-NEXT: }
// SETL-NEXT: ],
// SETL: "functionSignature": {
// SETL-NEXT: "parameters": [
// SETL-NEXT: {
// SETL-NEXT: "declarationFragments": [
// SETL-NEXT: {
// SETL-NEXT: "kind": "typeIdentifier",
// SETL-NEXT: "preciseIdentifier": "c:I",
// SETL-NEXT: "spelling": "int"
// SETL-NEXT: },
// SETL-NEXT: {
// SETL-NEXT: "kind": "text",
// SETL-NEXT: "spelling": " "
// SETL-NEXT: },
// SETL-NEXT: {
// SETL-NEXT: "kind": "internalParam",
// SETL-NEXT: "spelling": "length"
// SETL-NEXT: }
// SETL-NEXT: ],
// SETL-NEXT: "name": "length"
// SETL-NEXT: }
// SETL-NEXT: ],
// SETL-NEXT: "returns": [
// SETL-NEXT: {
// SETL-NEXT: "kind": "typeIdentifier",
// SETL-NEXT: "preciseIdentifier": "c:v",
// SETL-NEXT: "spelling": "void"
// SETL-NEXT: }
// SETL-NEXT: ]
// SETL-NEXT: },
public:
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GETFOO
static double getFoo();
// GETFOO: "!testRelLabel": "memberOf $ c:@S@Foo@F@getFoo#S $ c:@S@Foo"
// GETFOO-LABEL: "!testLabel": "c:@S@Foo@F@getFoo#S"
// GETFOO: "accessLevel": "public",
// GETFOO: "declarationFragments": [
// GETFOO-NEXT: {
// GETFOO-NEXT: "kind": "keyword",
// GETFOO-NEXT: "spelling": "static"
// GETFOO-NEXT: },
// GETFOO-NEXT: {
// GETFOO-NEXT: "kind": "text",
// GETFOO-NEXT: "spelling": " "
// GETFOO-NEXT: },
// GETFOO-NEXT: {
// GETFOO-NEXT: "kind": "typeIdentifier",
// GETFOO-NEXT: "preciseIdentifier": "c:d",
// GETFOO-NEXT: "spelling": "double"
// GETFOO-NEXT: },
// GETFOO-NEXT: {
// GETFOO-NEXT: "kind": "text",
// GETFOO-NEXT: "spelling": " "
// GETFOO-NEXT: },
// GETFOO-NEXT: {
// GETFOO-NEXT: "kind": "identifier",
// GETFOO-NEXT: "spelling": "getFoo"
// GETFOO-NEXT: },
// GETFOO-NEXT: {
// GETFOO-NEXT: "kind": "text",
// GETFOO-NEXT: "spelling": "();"
// GETFOO-NEXT: }
// GETFOO-NEXT: ],
// GETFOO: "functionSignature": {
// GETFOO-NEXT: "returns": [
// GETFOO-NEXT: {
// GETFOO-NEXT: "kind": "typeIdentifier",
// GETFOO-NEXT: "preciseIdentifier": "c:d",
// GETFOO-NEXT: "spelling": "double"
// GETFOO-NEXT: }
// GETFOO-NEXT: ]
// GETFOO-NEXT: },
// GETFOO: "kind": {
// GETFOO-NEXT: "displayName": "Static Method",
// GETFOO-NEXT: "identifier": "c++.type.method"
// GETFOO-NEXT: },
protected:
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GETBAR
constexpr int getBar() const;
// GETBAR: "!testRelLabel": "memberOf $ c:@S@Foo@F@getBar#1 $ c:@S@Foo"
// GETBAR-LABEL: "!testLabel": "c:@S@Foo@F@getBar#1"
// GETBAR: "accessLevel": "protected"
// GETBAR: "declarationFragments": [
// GETBAR-NEXT: {
// GETBAR-NEXT: "kind": "keyword",
// GETBAR-NEXT: "spelling": "constexpr"
// GETBAR-NEXT: },
// GETBAR-NEXT: {
// GETBAR-NEXT: "kind": "text",
// GETBAR-NEXT: "spelling": " "
// GETBAR-NEXT: },
// GETBAR-NEXT: {
// GETBAR-NEXT: "kind": "typeIdentifier",
// GETBAR-NEXT: "preciseIdentifier": "c:I",
// GETBAR-NEXT: "spelling": "int"
// GETBAR-NEXT: },
// GETBAR-NEXT: {
// GETBAR-NEXT: "kind": "text",
// GETBAR-NEXT: "spelling": " "
// GETBAR-NEXT: },
// GETBAR-NEXT: {
// GETBAR-NEXT: "kind": "identifier",
// GETBAR-NEXT: "spelling": "getBar"
// GETBAR-NEXT: },
// GETBAR-NEXT: {
// GETBAR-NEXT: "kind": "text",
// GETBAR-NEXT: "spelling": "() "
// GETBAR-NEXT: },
// GETBAR-NEXT: {
// GETBAR-NEXT: "kind": "keyword",
// GETBAR-NEXT: "spelling": "const"
// GETBAR-NEXT: },
// GETBAR-NEXT: {
// GETBAR-NEXT: "kind": "text",
// GETBAR-NEXT: "spelling": ";"
// GETBAR-NEXT: }
// GETBAR-NEXT: ],
};
/// expected-no-diagnostics
// expected-no-diagnostics
//--- reference.output.json.in
{
"metadata": {
"formatVersion": {
"major": 0,
"minor": 5,
"patch": 3
},
"generator": "?"
},
"module": {
"name": "",
"platform": {
"architecture": "arm64",
"operatingSystem": {
"minimumVersion": {
"major": 11,
"minor": 0,
"patch": 0
},
"name": "macosx"
},
"vendor": "apple"
}
},
"relationships": [
{
"kind": "memberOf",
"source": "c:@S@Foo@F@getCount#",
"target": "c:@S@Foo",
"targetFallback": "Foo"
},
{
"kind": "memberOf",
"source": "c:@S@Foo@F@setLength#I#",
"target": "c:@S@Foo",
"targetFallback": "Foo"
},
{
"kind": "memberOf",
"source": "c:@S@Foo@F@getBar#1",
"target": "c:@S@Foo",
"targetFallback": "Foo"
},
{
"kind": "memberOf",
"source": "c:@S@Foo@F@getFoo#S",
"target": "c:@S@Foo",
"targetFallback": "Foo"
}
],
"symbols": [
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "class"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "Foo"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c++",
"precise": "c:@S@Foo"
},
"kind": {
"displayName": "Class",
"identifier": "c++.class"
},
"location": {
"position": {
"character": 6,
"line": 0
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "Foo"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "Foo"
}
],
"title": "Foo"
},
"pathComponents": [
"Foo"
]
},
{
"accessLevel": "private",
"declarationFragments": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "getCount"
},
{
"kind": "text",
"spelling": "();"
}
],
"functionSignature": {
"returns": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
}
]
},
"identifier": {
"interfaceLanguage": "c++",
"precise": "c:@S@Foo@F@getCount#"
},
"kind": {
"displayName": "Instance Method",
"identifier": "c++.method"
},
"location": {
"position": {
"character": 6,
"line": 1
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "getCount"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "getCount"
}
],
"title": "getCount"
},
"pathComponents": [
"Foo",
"getCount"
]
},
{
"accessLevel": "private",
"declarationFragments": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "setLength"
},
{
"kind": "text",
"spelling": "("
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "internalParam",
"spelling": "length"
},
{
"kind": "text",
"spelling": ")"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "keyword",
"spelling": "noexcept"
},
{
"kind": "text",
"spelling": ";"
}
],
"functionSignature": {
"parameters": [
{
"declarationFragments": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "internalParam",
"spelling": "length"
}
],
"name": "length"
}
],
"returns": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
}
]
},
"identifier": {
"interfaceLanguage": "c++",
"precise": "c:@S@Foo@F@setLength#I#"
},
"kind": {
"displayName": "Instance Method",
"identifier": "c++.method"
},
"location": {
"position": {
"character": 7,
"line": 3
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "setLength"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "setLength"
}
],
"title": "setLength"
},
"pathComponents": [
"Foo",
"setLength"
]
},
{
"accessLevel": "protected",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "constexpr"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "getBar"
},
{
"kind": "text",
"spelling": "() "
},
{
"kind": "keyword",
"spelling": "const"
},
{
"kind": "text",
"spelling": ";"
}
],
"functionSignature": {
"returns": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
}
]
},
"identifier": {
"interfaceLanguage": "c++",
"precise": "c:@S@Foo@F@getBar#1"
},
"kind": {
"displayName": "Instance Method",
"identifier": "c++.method"
},
"location": {
"position": {
"character": 16,
"line": 9
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "getBar"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "getBar"
}
],
"title": "getBar"
},
"pathComponents": [
"Foo",
"getBar"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "static"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:d",
"spelling": "double"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "getFoo"
},
{
"kind": "text",
"spelling": "();"
}
],
"functionSignature": {
"returns": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:d",
"spelling": "double"
}
]
},
"identifier": {
"interfaceLanguage": "c++",
"precise": "c:@S@Foo@F@getFoo#S"
},
"kind": {
"displayName": "Static Method",
"identifier": "c++.type.method"
},
"location": {
"position": {
"character": 16,
"line": 6
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "getFoo"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "getFoo"
}
],
"title": "getFoo"
},
"pathComponents": [
"Foo",
"getFoo"
]
}
]
}

View File

@ -3,7 +3,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -std=c++20 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -std=c++20 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,341 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
// RUN: -triple arm64-apple-macosx -x objective-c-header %s -o - -verify | FileCheck %s
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \
// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
@protocol Protocol
@end
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
// RUN: %t/output.json >> %t/output-normalized.json
// RUN: diff %t/reference.output.json %t/output-normalized.json
// CHECK-NOT: error:
// CHECK-NOT: warning:
//--- input.h
@protocol Protocol;
@interface Interface
@end
@interface Interface (Category) <Protocol>
// CHECK-DAG: "!testRelLabel": "conformsTo $ c:objc(cs)Interface $ c:objc(pl)Protocol"
@property int Property;
// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(py)Property $ c:objc(cs)Interface"
- (void)InstanceMethod;
// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(im)InstanceMethod $ c:objc(cs)Interface"
+ (void)ClassMethod;
// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(cm)ClassMethod $ c:objc(cs)Interface"
@end
// expected-no-diagnostics
//--- reference.output.json.in
{
"metadata": {
"formatVersion": {
"major": 0,
"minor": 5,
"patch": 3
},
"generator": "?"
},
"module": {
"name": "",
"platform": {
"architecture": "arm64",
"operatingSystem": {
"minimumVersion": {
"major": 11,
"minor": 0,
"patch": 0
},
"name": "macosx"
},
"vendor": "apple"
}
},
"relationships": [
{
"kind": "memberOf",
"source": "c:objc(cs)Interface(im)InstanceMethod",
"target": "c:objc(cs)Interface",
"targetFallback": "Interface"
},
{
"kind": "memberOf",
"source": "c:objc(cs)Interface(cm)ClassMethod",
"target": "c:objc(cs)Interface",
"targetFallback": "Interface"
},
{
"kind": "memberOf",
"source": "c:objc(cs)Interface(py)Property",
"target": "c:objc(cs)Interface",
"targetFallback": "Interface"
},
{
"kind": "conformsTo",
"source": "c:objc(cs)Interface",
"target": "c:objc(pl)Protocol",
"targetFallback": "Protocol"
}
],
"symbols": [
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@interface"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "Interface"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)Interface"
},
"kind": {
"displayName": "Class",
"identifier": "objective-c.class"
},
"location": {
"position": {
"character": 11,
"line": 2
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "Interface"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "Interface"
}
],
"title": "Interface"
},
"pathComponents": [
"Interface"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "text",
"spelling": "- ("
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
},
{
"kind": "text",
"spelling": ") "
},
{
"kind": "identifier",
"spelling": "InstanceMethod"
},
{
"kind": "text",
"spelling": ";"
}
],
"functionSignature": {
"returns": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
}
]
},
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)Interface(im)InstanceMethod"
},
"kind": {
"displayName": "Instance Method",
"identifier": "objective-c.method"
},
"location": {
"position": {
"character": 0,
"line": 7
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "InstanceMethod"
}
],
"subHeading": [
{
"kind": "text",
"spelling": "- "
},
{
"kind": "identifier",
"spelling": "InstanceMethod"
}
],
"title": "InstanceMethod"
},
"pathComponents": [
"Interface",
"InstanceMethod"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "text",
"spelling": "+ ("
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
},
{
"kind": "text",
"spelling": ") "
},
{
"kind": "identifier",
"spelling": "ClassMethod"
},
{
"kind": "text",
"spelling": ";"
}
],
"functionSignature": {
"returns": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
}
]
},
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)Interface(cm)ClassMethod"
},
"kind": {
"displayName": "Type Method",
"identifier": "objective-c.type.method"
},
"location": {
"position": {
"character": 0,
"line": 8
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "ClassMethod"
}
],
"subHeading": [
{
"kind": "text",
"spelling": "+ "
},
{
"kind": "identifier",
"spelling": "ClassMethod"
}
],
"title": "ClassMethod"
},
"pathComponents": [
"Interface",
"ClassMethod"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@property"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "Property"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)Interface(py)Property"
},
"kind": {
"displayName": "Instance Property",
"identifier": "objective-c.property"
},
"location": {
"position": {
"character": 14,
"line": 6
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "Property"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "Property"
}
],
"title": "Property"
},
"pathComponents": [
"Interface",
"Property"
]
}
]
}

View File

@ -1,49 +0,0 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
// RUN: --emit-extension-symbol-graphs --symbol-graph-dir=%t/symbols \
// RUN: --product-name=Module -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules-cache \
// RUN: -triple arm64-apple-macosx -x objective-c-header %t/input.h -verify
//--- input.h
#include "ExternalModule.h"
@interface ExtInterface (Category)
@property int Property;
- (void)InstanceMethod;
+ (void)ClassMethod;
@end
@interface ModInterface
@end
// expected-no-diagnostics
//--- ExternalModule.h
@interface ExtInterface
@end
//--- module.modulemap
module ExternalModule {
header "ExternalModule.h"
}
// RUN: FileCheck %s --input-file %t/symbols/Module.symbols.json --check-prefix MOD
// MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(py)Property $ c:objc(cs)ExtInterface"
// MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(im)InstanceMethod $ c:objc(cs)ExtInterface"
// MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(cm)ClassMethod $ c:objc(cs)ExtInterface"
// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface(py)Property"
// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface(im)InstanceMethod"
// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface(cm)ClassMethod"
// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface"
// MOD-DAG: "!testLabel": "c:objc(cs)ModInterface"
// RUN: FileCheck %s --input-file %t/symbols/ExternalModule@Module.symbols.json --check-prefix EXT
// EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(py)Property $ c:objc(cs)ExtInterface"
// EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(im)InstanceMethod $ c:objc(cs)ExtInterface"
// EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(cm)ClassMethod $ c:objc(cs)ExtInterface"
// EXT-DAG: "!testLabel": "c:objc(cs)ExtInterface(py)Property"
// EXT-DAG: "!testLabel": "c:objc(cs)ExtInterface(im)InstanceMethod"
// EXT-DAG: "!testLabel": "c:objc(cs)ExtInterface(cm)ClassMethod"
// EXT-NOT: "!testLabel": "c:objc(cs)ExtInterface"
// EXT-NOT: "!testLabel": "c:objc(cs)ModInterface"

View File

@ -1,56 +1,317 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
// RUN: -x objective-c-header -triple arm64-apple-macosx %s -o - -verify | FileCheck %s
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \
// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
// RUN: %t/output.json >> %t/output-normalized.json
// RUN: diff %t/reference.output.json %t/output-normalized.json
// CHECK-NOT: error:
// CHECK-NOT: warning:
//--- input.h
@protocol MyProtocol
@end
@interface MyInterface
@property(copy, readwrite) id<MyProtocol> obj1;
// CHECK-LABEL: "!testLabel": "c:objc(cs)MyInterface(py)obj1"
// CHECK: "declarationFragments": [
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "keyword",
// CHECK-NEXT: "spelling": "@property"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "text",
// CHECK-NEXT: "spelling": " ("
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "keyword",
// CHECK-NEXT: "spelling": "copy"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "text",
// CHECK-NEXT: "spelling": ", "
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "keyword",
// CHECK-NEXT: "spelling": "readwrite"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "text",
// CHECK-NEXT: "spelling": ") "
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "typeIdentifier",
// CHECK-NEXT: "preciseIdentifier": "c:Qoobjc(pl)MyProtocol",
// CHECK-NEXT: "spelling": "id<MyProtocol>"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "text",
// CHECK-NEXT: "spelling": " "
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "identifier",
// CHECK-NEXT: "spelling": "obj1"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "kind": "text",
// CHECK-NEXT: "spelling": ";"
// CHECK-NEXT: }
// CHECK-NEXT: ],
@property(readwrite) id<MyProtocol> *obj2;
@end
// expected-no-diagnostics
//--- reference.output.json.in
{
"metadata": {
"formatVersion": {
"major": 0,
"minor": 5,
"patch": 3
},
"generator": "?"
},
"module": {
"name": "",
"platform": {
"architecture": "arm64",
"operatingSystem": {
"minimumVersion": {
"major": 11,
"minor": 0,
"patch": 0
},
"name": "macosx"
},
"vendor": "apple"
}
},
"relationships": [
{
"kind": "memberOf",
"source": "c:objc(cs)MyInterface(py)obj1",
"target": "c:objc(cs)MyInterface",
"targetFallback": "MyInterface"
},
{
"kind": "memberOf",
"source": "c:objc(cs)MyInterface(py)obj2",
"target": "c:objc(cs)MyInterface",
"targetFallback": "MyInterface"
}
],
"symbols": [
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@interface"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "MyInterface"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)MyInterface"
},
"kind": {
"displayName": "Class",
"identifier": "objective-c.class"
},
"location": {
"position": {
"character": 11,
"line": 3
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "MyInterface"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "MyInterface"
}
],
"title": "MyInterface"
},
"pathComponents": [
"MyInterface"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@property"
},
{
"kind": "text",
"spelling": " ("
},
{
"kind": "keyword",
"spelling": "copy"
},
{
"kind": "text",
"spelling": ", "
},
{
"kind": "keyword",
"spelling": "readwrite"
},
{
"kind": "text",
"spelling": ") "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:Qoobjc(pl)MyProtocol",
"spelling": "id<MyProtocol>"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "obj1"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)MyInterface(py)obj1"
},
"kind": {
"displayName": "Instance Property",
"identifier": "objective-c.property"
},
"location": {
"position": {
"character": 42,
"line": 4
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "obj1"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "obj1"
}
],
"title": "obj1"
},
"pathComponents": [
"MyInterface",
"obj1"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@property"
},
{
"kind": "text",
"spelling": " ("
},
{
"kind": "keyword",
"spelling": "readwrite"
},
{
"kind": "text",
"spelling": ") "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:Qoobjc(pl)MyProtocol",
"spelling": "id<MyProtocol>"
},
{
"kind": "text",
"spelling": " * "
},
{
"kind": "identifier",
"spelling": "obj2"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)MyInterface(py)obj2"
},
"kind": {
"displayName": "Instance Property",
"identifier": "objective-c.property"
},
"location": {
"position": {
"character": 37,
"line": 5
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "obj2"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "obj2"
}
],
"title": "obj2"
},
"pathComponents": [
"MyInterface",
"obj2"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@protocol"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "MyProtocol"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(pl)MyProtocol"
},
"kind": {
"displayName": "Protocol",
"identifier": "objective-c.protocol"
},
"location": {
"position": {
"character": 10,
"line": 0
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "MyProtocol"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "MyProtocol"
}
],
"title": "MyProtocol"
},
"pathComponents": [
"MyProtocol"
]
}
]
}

View File

@ -1,8 +1,8 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx -x objective-c-header %t/input.h -o %t/output.json -verify
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx -x objective-c-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,404 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang -extract-api -x objective-c-header \
// RUN: -target arm64-apple-macosx \
// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
// RUN: %t/output.json >> %t/output-normalized.json
// RUN: diff %t/reference.output.json %t/output-normalized.json
// CHECK-NOT: error:
// CHECK-NOT: warning:
//--- input.h
#import "Foundation.h"
/// Doc comment 1
@interface NSString (Category1)
-(void)method1;
@end
/// Doc comment 2
@interface NSString (Category2)
-(void)method2;
@end
//--- Foundation.h
@interface NSString
@end
//--- reference.output.json.in
{
"metadata": {
"formatVersion": {
"major": 0,
"minor": 5,
"patch": 3
},
"generator": "?"
},
"module": {
"name": "",
"platform": {
"architecture": "arm64",
"operatingSystem": {
"minimumVersion": {
"major": 11,
"minor": 0,
"patch": 0
},
"name": "macosx"
},
"vendor": "apple"
}
},
"relationships": [
{
"kind": "extensionTo",
"source": "c:objc(cy)NSString@Category1",
"target": "c:objc(cs)NSString",
"targetFallback": "NSString"
},
{
"kind": "memberOf",
"source": "c:objc(cs)NSString(im)method1",
"target": "c:objc(cy)NSString@Category1",
"targetFallback": "Category1"
},
{
"kind": "extensionTo",
"source": "c:objc(cy)NSString@Category2",
"target": "c:objc(cs)NSString",
"targetFallback": "NSString"
},
{
"kind": "memberOf",
"source": "c:objc(cs)NSString(im)method2",
"target": "c:objc(cy)NSString@Category2",
"targetFallback": "Category2"
}
],
"symbols": [
{
"accessLevel": "public",
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cy)NSString@Category1"
},
"kind": {
"displayName": "Module Extension",
"identifier": "objective-c.module.extension"
}
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@interface"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:objc(cs)NSString",
"spelling": "NSString"
},
{
"kind": "text",
"spelling": " ("
},
{
"kind": "identifier",
"spelling": "Category1"
},
{
"kind": "text",
"spelling": ")"
}
],
"docComment": {
"lines": [
{
"range": {
"end": {
"character": 17,
"line": 2
},
"start": {
"character": 4,
"line": 2
}
},
"text": "Doc comment 1"
}
]
},
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cy)NSString@Category1"
},
"kind": {
"displayName": "Class Extension",
"identifier": "objective-c.class.extension"
},
"location": {
"position": {
"character": 11,
"line": 3
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "Category1"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "Category1"
}
],
"title": "NSString (Category1)"
},
"pathComponents": [
"Category1"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "text",
"spelling": "- ("
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
},
{
"kind": "text",
"spelling": ") "
},
{
"kind": "identifier",
"spelling": "method1"
},
{
"kind": "text",
"spelling": ";"
}
],
"functionSignature": {
"returns": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
}
]
},
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)NSString(im)method1"
},
"kind": {
"displayName": "Instance Method",
"identifier": "objective-c.method"
},
"location": {
"position": {
"character": 0,
"line": 4
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "method1"
}
],
"subHeading": [
{
"kind": "text",
"spelling": "- "
},
{
"kind": "identifier",
"spelling": "method1"
}
],
"title": "method1"
},
"pathComponents": [
"Category1",
"method1"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@interface"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:objc(cs)NSString",
"spelling": "NSString"
},
{
"kind": "text",
"spelling": " ("
},
{
"kind": "identifier",
"spelling": "Category2"
},
{
"kind": "text",
"spelling": ")"
}
],
"docComment": {
"lines": [
{
"range": {
"end": {
"character": 17,
"line": 7
},
"start": {
"character": 4,
"line": 7
}
},
"text": "Doc comment 2"
}
]
},
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cy)NSString@Category2"
},
"kind": {
"displayName": "Class Extension",
"identifier": "objective-c.class.extension"
},
"location": {
"position": {
"character": 11,
"line": 8
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "Category2"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "Category2"
}
],
"title": "NSString (Category2)"
},
"pathComponents": [
"Category2"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "text",
"spelling": "- ("
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
},
{
"kind": "text",
"spelling": ") "
},
{
"kind": "identifier",
"spelling": "method2"
},
{
"kind": "text",
"spelling": ";"
}
],
"functionSignature": {
"returns": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
}
]
},
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)NSString(im)method2"
},
"kind": {
"displayName": "Instance Method",
"identifier": "objective-c.method"
},
"location": {
"position": {
"character": 0,
"line": 9
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "method2"
}
],
"subHeading": [
{
"kind": "text",
"spelling": "- "
},
{
"kind": "identifier",
"spelling": "method2"
}
],
"title": "method2"
},
"pathComponents": [
"Category2",
"method2"
]
}
]
}

View File

@ -1,26 +1,608 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
// RUN: -triple arm64-apple-macosx -x objective-c-header %s -o - -verify | FileCheck %s
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx -x objective-c-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
// RUN: %t/output.json >> %t/output-normalized.json
// RUN: diff %t/reference.output.json %t/output-normalized.json
//--- input.h
@protocol Protocol
@property(class) int myProtocolTypeProp;
// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(pl)Protocol(cpy)myProtocolTypeProp $ c:objc(pl)Protocol"
@property int myProtocolInstanceProp;
// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(pl)Protocol(py)myProtocolInstanceProp $ c:objc(pl)Protocol"
@end
@interface Interface
@property(class) int myInterfaceTypeProp;
// CHECk-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(cpy)myInterfaceTypeProp $ c:objc(cs)Interface"
@property int myInterfaceInstanceProp;
// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(py)myInterfaceInstanceProp $ c:objc(cs)Interface"
@end
@interface Interface (Category) <Protocol>
@property(class) int myCategoryTypeProp;
// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(cpy)myCategoryTypeProp $ c:objc(cs)Interface"
@property int myCategoryInstanceProp;
// CHECK-DAG "!testRelLabel": "memberOf $ c:objc(cs)Interface(py)myCategoryInstanceProp $ c:objc(cs)Interface"
@end
// expected-no-diagnostics
//--- reference.output.json.in
{
"metadata": {
"formatVersion": {
"major": 0,
"minor": 5,
"patch": 3
},
"generator": "?"
},
"module": {
"name": "",
"platform": {
"architecture": "arm64",
"operatingSystem": {
"minimumVersion": {
"major": 11,
"minor": 0,
"patch": 0
},
"name": "macosx"
},
"vendor": "apple"
}
},
"relationships": [
{
"kind": "memberOf",
"source": "c:objc(cs)Interface(cpy)myInterfaceTypeProp",
"target": "c:objc(cs)Interface",
"targetFallback": "Interface"
},
{
"kind": "memberOf",
"source": "c:objc(cs)Interface(py)myInterfaceInstanceProp",
"target": "c:objc(cs)Interface",
"targetFallback": "Interface"
},
{
"kind": "memberOf",
"source": "c:objc(cs)Interface(cpy)myCategoryTypeProp",
"target": "c:objc(cs)Interface",
"targetFallback": "Interface"
},
{
"kind": "memberOf",
"source": "c:objc(cs)Interface(py)myCategoryInstanceProp",
"target": "c:objc(cs)Interface",
"targetFallback": "Interface"
},
{
"kind": "conformsTo",
"source": "c:objc(cs)Interface",
"target": "c:objc(pl)Protocol",
"targetFallback": "Protocol"
},
{
"kind": "memberOf",
"source": "c:objc(pl)Protocol(cpy)myProtocolTypeProp",
"target": "c:objc(pl)Protocol",
"targetFallback": "Protocol"
},
{
"kind": "memberOf",
"source": "c:objc(pl)Protocol(py)myProtocolInstanceProp",
"target": "c:objc(pl)Protocol",
"targetFallback": "Protocol"
}
],
"symbols": [
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@interface"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "Interface"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)Interface"
},
"kind": {
"displayName": "Class",
"identifier": "objective-c.class"
},
"location": {
"position": {
"character": 11,
"line": 5
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "Interface"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "Interface"
}
],
"title": "Interface"
},
"pathComponents": [
"Interface"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@property"
},
{
"kind": "text",
"spelling": " ("
},
{
"kind": "keyword",
"spelling": "class"
},
{
"kind": "text",
"spelling": ") "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "myInterfaceTypeProp"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)Interface(cpy)myInterfaceTypeProp"
},
"kind": {
"displayName": "Type Property",
"identifier": "objective-c.type.property"
},
"location": {
"position": {
"character": 21,
"line": 6
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "myInterfaceTypeProp"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "myInterfaceTypeProp"
}
],
"title": "myInterfaceTypeProp"
},
"pathComponents": [
"Interface",
"myInterfaceTypeProp"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@property"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "myInterfaceInstanceProp"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)Interface(py)myInterfaceInstanceProp"
},
"kind": {
"displayName": "Instance Property",
"identifier": "objective-c.property"
},
"location": {
"position": {
"character": 14,
"line": 7
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "myInterfaceInstanceProp"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "myInterfaceInstanceProp"
}
],
"title": "myInterfaceInstanceProp"
},
"pathComponents": [
"Interface",
"myInterfaceInstanceProp"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@property"
},
{
"kind": "text",
"spelling": " ("
},
{
"kind": "keyword",
"spelling": "class"
},
{
"kind": "text",
"spelling": ") "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "myCategoryTypeProp"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)Interface(cpy)myCategoryTypeProp"
},
"kind": {
"displayName": "Type Property",
"identifier": "objective-c.type.property"
},
"location": {
"position": {
"character": 21,
"line": 11
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "myCategoryTypeProp"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "myCategoryTypeProp"
}
],
"title": "myCategoryTypeProp"
},
"pathComponents": [
"Interface",
"myCategoryTypeProp"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@property"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "myCategoryInstanceProp"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)Interface(py)myCategoryInstanceProp"
},
"kind": {
"displayName": "Instance Property",
"identifier": "objective-c.property"
},
"location": {
"position": {
"character": 14,
"line": 12
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "myCategoryInstanceProp"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "myCategoryInstanceProp"
}
],
"title": "myCategoryInstanceProp"
},
"pathComponents": [
"Interface",
"myCategoryInstanceProp"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@protocol"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "Protocol"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(pl)Protocol"
},
"kind": {
"displayName": "Protocol",
"identifier": "objective-c.protocol"
},
"location": {
"position": {
"character": 10,
"line": 0
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "Protocol"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "Protocol"
}
],
"title": "Protocol"
},
"pathComponents": [
"Protocol"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@property"
},
{
"kind": "text",
"spelling": " ("
},
{
"kind": "keyword",
"spelling": "class"
},
{
"kind": "text",
"spelling": ") "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "myProtocolTypeProp"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(pl)Protocol(cpy)myProtocolTypeProp"
},
"kind": {
"displayName": "Type Property",
"identifier": "objective-c.type.property"
},
"location": {
"position": {
"character": 21,
"line": 1
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "myProtocolTypeProp"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "myProtocolTypeProp"
}
],
"title": "myProtocolTypeProp"
},
"pathComponents": [
"Protocol",
"myProtocolTypeProp"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@property"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "myProtocolInstanceProp"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(pl)Protocol(py)myProtocolInstanceProp"
},
"kind": {
"displayName": "Instance Property",
"identifier": "objective-c.property"
},
"location": {
"position": {
"character": 14,
"line": 2
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "myProtocolInstanceProp"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "myProtocolInstanceProp"
}
],
"title": "myProtocolInstanceProp"
},
"pathComponents": [
"Protocol",
"myProtocolInstanceProp"
]
}
]
}

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang -extract-api --pretty-sgf -x objective-c-header -target arm64-apple-macosx \
// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \
// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.

View File

@ -0,0 +1,507 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang -extract-api -x objective-c-header \
// RUN: -target arm64-apple-macosx \
// RUN: %t/myclass_1.h \
// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
// RUN: %t/output.json >> %t/output-normalized.json
// RUN: diff %t/reference.output.json %t/output-normalized.json
// CHECK-NOT: error:
// CHECK-NOT: warning:
//--- input.h
#import "myclass_1.h"
#import "Foundation.h"
@interface MyClass1 (MyCategory1)
- (int) SomeMethod;
@end
@interface NSString (Category1)
-(void) StringMethod;
@end
@interface NSString (Category2)
-(void) StringMethod2;
@end
//--- myclass_1.h
@interface MyClass1
@end
//--- Foundation.h
@interface NSString
@end
//--- reference.output.json.in
{
"metadata": {
"formatVersion": {
"major": 0,
"minor": 5,
"patch": 3
},
"generator": "?"
},
"module": {
"name": "",
"platform": {
"architecture": "arm64",
"operatingSystem": {
"minimumVersion": {
"major": 11,
"minor": 0,
"patch": 0
},
"name": "macosx"
},
"vendor": "apple"
}
},
"relationships": [
{
"kind": "memberOf",
"source": "c:objc(cs)MyClass1(im)SomeMethod",
"target": "c:objc(cs)MyClass1",
"targetFallback": "MyClass1"
},
{
"kind": "extensionTo",
"source": "c:objc(cy)NSString@Category1",
"target": "c:objc(cs)NSString",
"targetFallback": "NSString"
},
{
"kind": "memberOf",
"source": "c:objc(cs)NSString(im)StringMethod",
"target": "c:objc(cy)NSString@Category1",
"targetFallback": "Category1"
},
{
"kind": "extensionTo",
"source": "c:objc(cy)NSString@Category2",
"target": "c:objc(cs)NSString",
"targetFallback": "NSString"
},
{
"kind": "memberOf",
"source": "c:objc(cs)NSString(im)StringMethod2",
"target": "c:objc(cy)NSString@Category2",
"targetFallback": "Category2"
}
],
"symbols": [
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@interface"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "MyClass1"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)MyClass1"
},
"kind": {
"displayName": "Class",
"identifier": "objective-c.class"
},
"location": {
"position": {
"character": 11,
"line": 0
},
"uri": "file://INPUT_DIR/myclass_1.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "MyClass1"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "MyClass1"
}
],
"title": "MyClass1"
},
"pathComponents": [
"MyClass1"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "text",
"spelling": "- ("
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": ") "
},
{
"kind": "identifier",
"spelling": "SomeMethod"
},
{
"kind": "text",
"spelling": ";"
}
],
"functionSignature": {
"returns": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
}
]
},
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)MyClass1(im)SomeMethod"
},
"kind": {
"displayName": "Instance Method",
"identifier": "objective-c.method"
},
"location": {
"position": {
"character": 0,
"line": 4
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "SomeMethod"
}
],
"subHeading": [
{
"kind": "text",
"spelling": "- "
},
{
"kind": "identifier",
"spelling": "SomeMethod"
}
],
"title": "SomeMethod"
},
"pathComponents": [
"MyClass1",
"SomeMethod"
]
},
{
"accessLevel": "public",
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cy)NSString@Category1"
},
"kind": {
"displayName": "Module Extension",
"identifier": "objective-c.module.extension"
}
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@interface"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:objc(cs)NSString",
"spelling": "NSString"
},
{
"kind": "text",
"spelling": " ("
},
{
"kind": "identifier",
"spelling": "Category1"
},
{
"kind": "text",
"spelling": ")"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cy)NSString@Category1"
},
"kind": {
"displayName": "Class Extension",
"identifier": "objective-c.class.extension"
},
"location": {
"position": {
"character": 11,
"line": 7
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "Category1"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "Category1"
}
],
"title": "NSString (Category1)"
},
"pathComponents": [
"Category1"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "text",
"spelling": "- ("
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
},
{
"kind": "text",
"spelling": ") "
},
{
"kind": "identifier",
"spelling": "StringMethod"
},
{
"kind": "text",
"spelling": ";"
}
],
"functionSignature": {
"returns": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
}
]
},
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)NSString(im)StringMethod"
},
"kind": {
"displayName": "Instance Method",
"identifier": "objective-c.method"
},
"location": {
"position": {
"character": 0,
"line": 8
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "StringMethod"
}
],
"subHeading": [
{
"kind": "text",
"spelling": "- "
},
{
"kind": "identifier",
"spelling": "StringMethod"
}
],
"title": "StringMethod"
},
"pathComponents": [
"Category1",
"StringMethod"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "@interface"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:objc(cs)NSString",
"spelling": "NSString"
},
{
"kind": "text",
"spelling": " ("
},
{
"kind": "identifier",
"spelling": "Category2"
},
{
"kind": "text",
"spelling": ")"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cy)NSString@Category2"
},
"kind": {
"displayName": "Class Extension",
"identifier": "objective-c.class.extension"
},
"location": {
"position": {
"character": 11,
"line": 11
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "Category2"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "Category2"
}
],
"title": "NSString (Category2)"
},
"pathComponents": [
"Category2"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "text",
"spelling": "- ("
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
},
{
"kind": "text",
"spelling": ") "
},
{
"kind": "identifier",
"spelling": "StringMethod2"
},
{
"kind": "text",
"spelling": ";"
}
],
"functionSignature": {
"returns": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
}
]
},
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:objc(cs)NSString(im)StringMethod2"
},
"kind": {
"displayName": "Instance Method",
"identifier": "objective-c.method"
},
"location": {
"position": {
"character": 0,
"line": 12
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "StringMethod2"
}
],
"subHeading": [
{
"kind": "text",
"spelling": "- "
},
{
"kind": "identifier",
"spelling": "StringMethod2"
}
],
"title": "StringMethod2"
},
"pathComponents": [
"Category2",
"StringMethod2"
]
}
]
}

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -15,7 +15,7 @@
// RUN: %hmaptool write %t/headermap.hmap.json %t/headermap.hmap
// Input headers use paths to the framework root/DSTROOT
// RUN: %clang_cc1 -extract-api --pretty-sgf -v --product-name=MyFramework \
// RUN: %clang_cc1 -extract-api -v --product-name=MyFramework \
// RUN: -triple arm64-apple-macosx \
// RUN: -iquote%t -I%t/headermap.hmap -F%t/Frameworks \
// RUN: -x objective-c-header \

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang -extract-api --pretty-sgf -target arm64-apple-macosx \
// RUN: %clang -extract-api -target arm64-apple-macosx \
// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.

View File

@ -1,93 +1,391 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
// RUN: -triple arm64-apple-macosx -x objective-c-header %s -o %t/output.symbols.json -verify
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang -extract-api --product-name=Typedef -target arm64-apple-macosx \
// RUN: -x objective-c-header %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix MYINT
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
// RUN: %t/output.json >> %t/output-normalized.json
// RUN: diff %t/reference.output.json %t/output-normalized.json
// CHECK-NOT: error:
// CHECK-NOT: warning:
//--- input.h
typedef int MyInt;
// MYINT-LABEL: "!testLabel": "c:typedef.c@T@MyInt"
// MYINT: "accessLevel": "public",
// MYINT: "declarationFragments": [
// MYINT-NEXT: {
// MYINT-NEXT: "kind": "keyword",
// MYINT-NEXT: "spelling": "typedef"
// MYINT-NEXT: },
// MYINT-NEXT: {
// MYINT-NEXT: "kind": "text",
// MYINT-NEXT: "spelling": " "
// MYINT-NEXT: },
// MYINT-NEXT: {
// MYINT-NEXT: "kind": "typeIdentifier",
// MYINT-NEXT: "preciseIdentifier": "c:I",
// MYINT-NEXT: "spelling": "int"
// MYINT-NEXT: },
// MYINT-NEXT: {
// MYINT-NEXT: "kind": "text",
// MYINT-NEXT: "spelling": " "
// MYINT-NEXT: },
// MYINT-NEXT: {
// MYINT-NEXT: "kind": "identifier",
// MYINT-NEXT: "spelling": "MyInt"
// MYINT-NEXT: },
// MYINT-NEXT: {
// MYINT-NEXT: "kind": "text",
// MYINT-NEXT: "spelling": ";"
// MYINT-NEXT: }
// MYINT-NEXT: ],
// MYINT: "kind": {
// MYINT-NEXT: "displayName": "Type Alias",
// MYINT-NEXT: "identifier": "objective-c.typealias"
// MYINT-NEXT: },
// MYINT: "title": "MyInt"
// MYINT: "pathComponents": [
// MYINT-NEXT: "MyInt"
// MYINT-NEXT: ],
// MYINT: "type": "c:I"
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix BARPTR
typedef struct Bar *BarPtr;
// BARPTR-LABEL: "!testLabel": "c:typedef.c@T@BarPtr"
// BARPTR: "accessLevel": "public",
// BARPTR: "declarationFragments": [
// BARPTR-NEXT: {
// BARPTR-NEXT: "kind": "keyword",
// BARPTR-NEXT: "spelling": "typedef"
// BARPTR-NEXT: },
// BARPTR-NEXT: {
// BARPTR-NEXT: "kind": "text",
// BARPTR-NEXT: "spelling": " "
// BARPTR-NEXT: },
// BARPTR-NEXT: {
// BARPTR-NEXT: "kind": "keyword",
// BARPTR-NEXT: "spelling": "struct"
// BARPTR-NEXT: },
// BARPTR-NEXT: {
// BARPTR-NEXT: "kind": "text",
// BARPTR-NEXT: "spelling": " "
// BARPTR-NEXT: },
// BARPTR-NEXT: {
// BARPTR-NEXT: "kind": "typeIdentifier",
// BARPTR-NEXT: "preciseIdentifier": "c:@S@Bar",
// BARPTR-NEXT: "spelling": "Bar"
// BARPTR-NEXT: },
// BARPTR-NEXT: {
// BARPTR-NEXT: "kind": "text",
// BARPTR-NEXT: "spelling": " * "
// BARPTR-NEXT: },
// BARPTR-NEXT: {
// BARPTR-NEXT: "kind": "identifier",
// BARPTR-NEXT: "spelling": "BarPtr"
// BARPTR-NEXT: },
// BARPTR-NEXT: {
// BARPTR-NEXT: "kind": "text",
// BARPTR-NEXT: "spelling": ";"
// BARPTR-NEXT: }
// BARPTR-NEXT: ],
// BARPTR: "type": "c:*$@S@Bar"
// RUN: FileCheck %s --input-file %t/output.symbols.json
void foo(BarPtr value);
void baz(BarPtr *value);
// CHECK-NOT: struct Bar *
// expected-no-diagnostics
//--- reference.output.json.in
{
"metadata": {
"formatVersion": {
"major": 0,
"minor": 5,
"patch": 3
},
"generator": "?"
},
"module": {
"name": "Typedef",
"platform": {
"architecture": "arm64",
"operatingSystem": {
"minimumVersion": {
"major": 11,
"minor": 0,
"patch": 0
},
"name": "macosx"
},
"vendor": "apple"
}
},
"relationships": [],
"symbols": [
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "foo"
},
{
"kind": "text",
"spelling": "("
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:input.h@T@BarPtr",
"spelling": "BarPtr"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "internalParam",
"spelling": "value"
},
{
"kind": "text",
"spelling": ");"
}
],
"functionSignature": {
"parameters": [
{
"declarationFragments": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:input.h@T@BarPtr",
"spelling": "BarPtr"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "internalParam",
"spelling": "value"
}
],
"name": "value"
}
],
"returns": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
}
]
},
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:@F@foo"
},
"kind": {
"displayName": "Function",
"identifier": "objective-c.func"
},
"location": {
"position": {
"character": 5,
"line": 4
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "foo"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "foo"
}
],
"title": "foo"
},
"pathComponents": [
"foo"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "baz"
},
{
"kind": "text",
"spelling": "("
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:input.h@T@BarPtr",
"spelling": "BarPtr"
},
{
"kind": "text",
"spelling": " * "
},
{
"kind": "internalParam",
"spelling": "value"
},
{
"kind": "text",
"spelling": ");"
}
],
"functionSignature": {
"parameters": [
{
"declarationFragments": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:input.h@T@BarPtr",
"spelling": "BarPtr"
},
{
"kind": "text",
"spelling": " * "
},
{
"kind": "internalParam",
"spelling": "value"
}
],
"name": "value"
}
],
"returns": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:v",
"spelling": "void"
}
]
},
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:@F@baz"
},
"kind": {
"displayName": "Function",
"identifier": "objective-c.func"
},
"location": {
"position": {
"character": 5,
"line": 6
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "baz"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "baz"
}
],
"title": "baz"
},
"pathComponents": [
"baz"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "typedef"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "MyInt"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:input.h@T@MyInt"
},
"kind": {
"displayName": "Type Alias",
"identifier": "objective-c.typealias"
},
"location": {
"position": {
"character": 12,
"line": 0
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "MyInt"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "MyInt"
}
],
"title": "MyInt"
},
"pathComponents": [
"MyInt"
],
"type": "c:I"
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "typedef"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "keyword",
"spelling": "struct"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:@S@Bar",
"spelling": "Bar"
},
{
"kind": "text",
"spelling": " * "
},
{
"kind": "identifier",
"spelling": "BarPtr"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "objective-c",
"precise": "c:input.h@T@BarPtr"
},
"kind": {
"displayName": "Type Alias",
"identifier": "objective-c.typealias"
},
"location": {
"position": {
"character": 20,
"line": 2
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "BarPtr"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "BarPtr"
}
],
"title": "BarPtr"
},
"pathComponents": [
"BarPtr"
],
"type": "c:*$@S@Bar"
}
]
}

View File

@ -1,158 +1,468 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
// RUN: --product-name=TypedefChain -triple arm64-apple-macosx -x c-header %s -o %t/typedefchain.symbols.json -verify
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --product-name=TypedefChain -triple arm64-apple-macosx \
// RUN: -x c-header %t/input.h -o %t/output.json -verify
// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYSTRUCT
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
// RUN: %t/output.json >> %t/output-normalized.json
// RUN: diff %t/reference.output.json %t/output-normalized.json
//--- input.h
typedef struct { } MyStruct;
// MYSTRUCT-LABEL: "!testLabel": "c:@SA@MyStruct"
// MYSTRUCT: "accessLevel": "public",
// MYSTRUCT: "declarationFragments": [
// MYSTRUCT-NEXT: {
// MYSTRUCT-NEXT: "kind": "keyword",
// MYSTRUCT-NEXT: "spelling": "typedef"
// MYSTRUCT-NEXT: },
// MYSTRUCT-NEXT: {
// MYSTRUCT-NEXT: "kind": "text",
// MYSTRUCT-NEXT: "spelling": " "
// MYSTRUCT-NEXT: },
// MYSTRUCT-NEXT: {
// MYSTRUCT-NEXT: "kind": "keyword",
// MYSTRUCT-NEXT: "spelling": "struct"
// MYSTRUCT-NEXT: },
// MYSTRUCT-NEXT: {
// MYSTRUCT-NEXT: "kind": "text",
// MYSTRUCT-NEXT: "spelling": " "
// MYSTRUCT-NEXT: },
// MYSTRUCT-NEXT: {
// MYSTRUCT-NEXT: "kind": "identifier",
// MYSTRUCT-NEXT: "spelling": "MyStruct"
// MYSTRUCT-NEXT: },
// MYSTRUCT-NEXT: {
// MYSTRUCT-NEXT: "kind": "text",
// MYSTRUCT-NEXT: "spelling": ";"
// MYSTRUCT-NEXT: }
// MYSTRUCT-NEXT: ]
// MYSTRUCT: "kind": {
// MYSTRUCT-NEXT: "displayName": "Structure",
// MYSTRUCT-NEXT: "identifier": "c.struct"
// MYSTRUCT: "title": "MyStruct"
// MYSTRUCT: "pathComponents": [
// MYSTRUCT-NEXT: "MyStruct"
// MYSTRUCT-NEXT: ]
// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYSTRUCTSTRUCT
typedef MyStruct MyStructStruct;
// MYSTRUCTSTRUCT-LABEL: "!testLabel": "c:typedef_anonymous_record.c@T@MyStructStruct"
// MYSTRUCTSTRUCT: "accessLevel": "public",
// MYSTRUCTSTRUCT: "declarationFragments": [
// MYSTRUCTSTRUCT-NEXT: {
// MYSTRUCTSTRUCT-NEXT: "kind": "keyword",
// MYSTRUCTSTRUCT-NEXT: "spelling": "typedef"
// MYSTRUCTSTRUCT-NEXT: },
// MYSTRUCTSTRUCT-NEXT: {
// MYSTRUCTSTRUCT-NEXT: "kind": "text",
// MYSTRUCTSTRUCT-NEXT: "spelling": " "
// MYSTRUCTSTRUCT-NEXT: },
// MYSTRUCTSTRUCT-NEXT: {
// MYSTRUCTSTRUCT-NEXT: "kind": "typeIdentifier",
// MYSTRUCTSTRUCT-NEXT: "preciseIdentifier": "c:@SA@MyStruct",
// MYSTRUCTSTRUCT-NEXT: "spelling": "MyStruct"
// MYSTRUCTSTRUCT-NEXT: },
// MYSTRUCTSTRUCT-NEXT: {
// MYSTRUCTSTRUCT-NEXT: "kind": "text",
// MYSTRUCTSTRUCT-NEXT: "spelling": " "
// MYSTRUCTSTRUCT-NEXT: },
// MYSTRUCTSTRUCT-NEXT: {
// MYSTRUCTSTRUCT-NEXT: "kind": "identifier",
// MYSTRUCTSTRUCT-NEXT: "spelling": "MyStructStruct"
// MYSTRUCTSTRUCT-NEXT: },
// MYSTRUCTSTRUCT-NEXT: {
// MYSTRUCTSTRUCT-NEXT: "kind": "text",
// MYSTRUCTSTRUCT-NEXT: "spelling": ";"
// MYSTRUCTSTRUCT-NEXT: }
// MYSTRUCTSTRUCT-NEXT:],
// MYSTRUCTSTRUCT: "kind": {
// MYSTRUCTSTRUCT-NEXT: "displayName": "Type Alias",
// MYSTRUCTSTRUCT-NEXT: "identifier": "c.typealias"
// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYENUM
// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix CASE
typedef MyStructStruct MyStructStructStruct;
typedef enum { Case } MyEnum;
// MYENUM: "source": "c:@EA@MyEnum@Case",
// MYENUM-NEXT: "target": "c:@EA@MyEnum",
// MYENUM-NEXT: "targetFallback": "MyEnum"
// MYENUM-LABEL: "!testLabel": "c:@EA@MyEnum"
// MYENUM: "declarationFragments": [
// MYENUM-NEXT: {
// MYENUM-NEXT: "kind": "keyword",
// MYENUM-NEXT: "spelling": "typedef"
// MYENUM-NEXT: },
// MYENUM-NEXT: {
// MYENUM-NEXT: "kind": "text",
// MYENUM-NEXT: "spelling": " "
// MYENUM-NEXT: },
// MYENUM-NEXT: {
// MYENUM-NEXT: "kind": "keyword",
// MYENUM-NEXT: "spelling": "enum"
// MYENUM-NEXT: },
// MYENUM-NEXT: {
// MYENUM-NEXT: "kind": "text",
// MYENUM-NEXT: "spelling": " "
// MYENUM-NEXT: },
// MYENUM-NEXT: {
// MYENUM-NEXT: "kind": "identifier",
// MYENUM-NEXT: "spelling": "MyEnum"
// MYENUM-NEXT: },
// MYENUM-NEXT: {
// MYENUM-NEXT: "kind": "text",
// MYENUM-NEXT: "spelling": ";"
// MYENUM-NEXT: }
// MYENUM-NEXT:],
// MYENUM: "kind": {
// MYENUM-NEXT: "displayName": "Enumeration",
// MYENUM-NEXT: "identifier": "c.enum"
// MYENUM: "title": "MyEnum"
// CASE-LABEL: "!testLabel": "c:@EA@MyEnum@Case"
// CASE: "pathComponents": [
// CASE-NEXT: "MyEnum",
// CASE-NEXT: "Case"
// CASE-NEXT: ]
// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYENUMENUM
typedef MyEnum MyEnumEnum;
// MYENUMENUM-LABEL: "!testLabel": "c:typedef_anonymous_record.c@T@MyEnumEnum"
// MYENUMENUM: "declarationFragments": [
// MYENUMENUM-NEXT: {
// MYENUMENUM-NEXT: "kind": "keyword",
// MYENUMENUM-NEXT: "spelling": "typedef"
// MYENUMENUM-NEXT: },
// MYENUMENUM-NEXT: {
// MYENUMENUM-NEXT: "kind": "text",
// MYENUMENUM-NEXT: "spelling": " "
// MYENUMENUM-NEXT: },
// MYENUMENUM-NEXT: {
// MYENUMENUM-NEXT: "kind": "typeIdentifier",
// MYENUMENUM-NEXT: "preciseIdentifier": "c:@EA@MyEnum",
// MYENUMENUM-NEXT: "spelling": "MyEnum"
// MYENUMENUM-NEXT: },
// MYENUMENUM-NEXT: {
// MYENUMENUM-NEXT: "kind": "text",
// MYENUMENUM-NEXT: "spelling": " "
// MYENUMENUM-NEXT: },
// MYENUMENUM-NEXT: {
// MYENUMENUM-NEXT: "kind": "identifier",
// MYENUMENUM-NEXT: "spelling": "MyEnumEnum"
// MYENUMENUM-NEXT: },
// MYENUMENUM-NEXT: {
// MYENUMENUM-NEXT: "kind": "text",
// MYENUMENUM-NEXT: "spelling": ";"
// MYENUMENUM-NEXT: }
// MYENUMENUM-NEXT: ],
// MYENUMENUM: "kind": {
// MYENUMENUM-NEXT: "displayName": "Type Alias",
// MYENUMENUM-NEXT: "identifier": "c.typealias"
// MYENUMENUM-NEXT: },
// MYENUMENUM: "title": "MyEnumEnum"
typedef MyEnumEnum MyEnumEnumEnum;
// expected-no-diagnostics
//--- reference.output.json.in
{
"metadata": {
"formatVersion": {
"major": 0,
"minor": 5,
"patch": 3
},
"generator": "?"
},
"module": {
"name": "TypedefChain",
"platform": {
"architecture": "arm64",
"operatingSystem": {
"minimumVersion": {
"major": 11,
"minor": 0,
"patch": 0
},
"name": "macosx"
},
"vendor": "apple"
}
},
"relationships": [
{
"kind": "memberOf",
"source": "c:@EA@MyEnum@Case",
"target": "c:@EA@MyEnum",
"targetFallback": "MyEnum"
}
],
"symbols": [
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "typedef"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "keyword",
"spelling": "enum"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "MyEnum"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:@EA@MyEnum"
},
"kind": {
"displayName": "Enumeration",
"identifier": "c.enum"
},
"location": {
"position": {
"character": 8,
"line": 3
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "MyEnum"
}
],
"title": "MyEnum"
},
"pathComponents": [
"MyEnum"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "identifier",
"spelling": "Case"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:@EA@MyEnum@Case"
},
"kind": {
"displayName": "Enumeration Case",
"identifier": "c.enum.case"
},
"location": {
"position": {
"character": 15,
"line": 3
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "Case"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "Case"
}
],
"title": "Case"
},
"pathComponents": [
"MyEnum",
"Case"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "typedef"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "keyword",
"spelling": "struct"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "MyStruct"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:@SA@MyStruct"
},
"kind": {
"displayName": "Structure",
"identifier": "c.struct"
},
"location": {
"position": {
"character": 8,
"line": 0
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "MyStruct"
}
],
"title": "MyStruct"
},
"pathComponents": [
"MyStruct"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "typedef"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:@SA@MyStruct",
"spelling": "MyStruct"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "MyStructStruct"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:input.h@T@MyStructStruct"
},
"kind": {
"displayName": "Type Alias",
"identifier": "c.typealias"
},
"location": {
"position": {
"character": 17,
"line": 1
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "MyStructStruct"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "MyStructStruct"
}
],
"title": "MyStructStruct"
},
"pathComponents": [
"MyStructStruct"
],
"type": "c:@SA@MyStruct"
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "typedef"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:input.h@T@MyStructStruct",
"spelling": "MyStructStruct"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "MyStructStructStruct"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:input.h@T@MyStructStructStruct"
},
"kind": {
"displayName": "Type Alias",
"identifier": "c.typealias"
},
"location": {
"position": {
"character": 23,
"line": 2
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "MyStructStructStruct"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "MyStructStructStruct"
}
],
"title": "MyStructStructStruct"
},
"pathComponents": [
"MyStructStructStruct"
],
"type": "c:input.h@T@MyStructStruct"
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "typedef"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:@EA@MyEnum",
"spelling": "MyEnum"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "MyEnumEnum"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:input.h@T@MyEnumEnum"
},
"kind": {
"displayName": "Type Alias",
"identifier": "c.typealias"
},
"location": {
"position": {
"character": 15,
"line": 4
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "MyEnumEnum"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "MyEnumEnum"
}
],
"title": "MyEnumEnum"
},
"pathComponents": [
"MyEnumEnum"
],
"type": "c:@EA@MyEnum"
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "typedef"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:input.h@T@MyEnumEnum",
"spelling": "MyEnumEnum"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "MyEnumEnumEnum"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:input.h@T@MyEnumEnumEnum"
},
"kind": {
"displayName": "Type Alias",
"identifier": "c.typealias"
},
"location": {
"position": {
"character": 19,
"line": 5
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "MyEnumEnumEnum"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "MyEnumEnumEnum"
}
],
"title": "MyEnumEnumEnum"
},
"pathComponents": [
"MyEnumEnumEnum"
],
"type": "c:input.h@T@MyEnumEnum"
}
]
}

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang -extract-api --pretty-sgf --product-name=TypedefChain -target arm64-apple-macosx \
// RUN: %clang -extract-api --product-name=TypedefChain -target arm64-apple-macosx \
// RUN: -x objective-c-header %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.

View File

@ -1,146 +1,445 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
// RUN: -x c-header %s -triple arm64-apple-macos -o %t/output.symbols.json -verify
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang -extract-api -target arm64-apple-macosx \
// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix TEST
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
// RUN: %t/output.json >> %t/output-normalized.json
// RUN: diff %t/reference.output.json %t/output-normalized.json
// CHECK-NOT: error:
// CHECK-NOT: warning:
//--- input.h
typedef struct Test {
} Test;
// TEST-LABEL: "!testLabel": "c:@S@Test"
// TEST: "declarationFragments": [
// TEST-NEXT: {
// TEST-NEXT: "kind": "keyword",
// TEST-NEXT: "spelling": "typedef"
// TEST-NEXT: },
// TEST-NEXT: {
// TEST-NEXT: "kind": "text",
// TEST-NEXT: "spelling": " "
// TEST-NEXT: },
// TEST-NEXT: {
// TEST-NEXT: "kind": "keyword",
// TEST-NEXT: "spelling": "struct"
// TEST-NEXT: },
// TEST-NEXT: {
// TEST-NEXT: "kind": "text",
// TEST-NEXT: "spelling": " "
// TEST-NEXT: },
// TEST-NEXT: {
// TEST-NEXT: "kind": "identifier",
// TEST-NEXT: "spelling": "Test"
// TEST-NEXT: },
// TEST-NEXT: {
// TEST-NEXT: "kind": "text",
// TEST-NEXT: "spelling": " { ... } "
// TEST-NEXT: },
// TEST-NEXT: {
// TEST-NEXT: "kind": "identifier",
// TEST-NEXT: "spelling": "Test"
// TEST-NEXT: },
// TEST-NEXT: {
// TEST-NEXT: "kind": "text",
// TEST-NEXT: "spelling": ";"
// TEST-NEXT: }
// TEST-NEXT: ],
// TEST: "displayName": "Structure",
// TEST: "title": "Test"
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix TEST2
typedef enum Test2 {
simple
} Test2;
// TEST2-LABEL: "!testLabel": "c:@E@Test2"
// TEST2: "declarationFragments": [
// TEST2-NEXT: {
// TEST2-NEXT: "kind": "keyword",
// TEST2-NEXT: "spelling": "typedef"
// TEST2-NEXT: },
// TEST2-NEXT: {
// TEST2-NEXT: "kind": "text",
// TEST2-NEXT: "spelling": " "
// TEST2-NEXT: },
// TEST2-NEXT: {
// TEST2-NEXT: "kind": "keyword",
// TEST2-NEXT: "spelling": "enum"
// TEST2-NEXT: },
// TEST2-NEXT: {
// TEST2-NEXT: "kind": "text",
// TEST2-NEXT: "spelling": " "
// TEST2-NEXT: },
// TEST2-NEXT: {
// TEST2-NEXT: "kind": "identifier",
// TEST2-NEXT: "spelling": "Test2"
// TEST2-NEXT: },
// TEST2-NEXT: {
// TEST2-NEXT: "kind": "text",
// TEST2-NEXT: "spelling": ": "
// TEST2-NEXT: },
// TEST2-NEXT: {
// TEST2-NEXT: "kind": "typeIdentifier",
// TEST2-NEXT: "preciseIdentifier": "c:i",
// TEST2-NEXT: "spelling": "unsigned int"
// TEST2-NEXT: },
// TEST2-NEXT: {
// TEST2-NEXT: "kind": "text",
// TEST2-NEXT: "spelling": " { ... } "
// TEST2-NEXT: },
// TEST2-NEXT: {
// TEST2-NEXT: "kind": "identifier",
// TEST2-NEXT: "spelling": "Test2"
// TEST2-NEXT: },
// TEST2-NEXT: {
// TEST2-NEXT: "kind": "text",
// TEST2-NEXT: "spelling": ";"
// TEST2-NEXT: }
// TEST2-NEXT: ],
// TEST2: "displayName": "Enumeration",
// TEST2: "title": "Test2"
struct Foo;
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix TYPEDEF
typedef struct Foo TypedefedFoo;
// TYPEDEF-LABEL: "!testLabel": "c:typedef_struct_enum.c@T@TypedefedFoo"
// TYPEDEF: "declarationFragments": [
// TYPEDEF-NEXT: {
// TYPEDEF-NEXT: "kind": "keyword",
// TYPEDEF-NEXT: "spelling": "typedef"
// TYPEDEF-NEXT: },
// TYPEDEF-NEXT: {
// TYPEDEF-NEXT: "kind": "text",
// TYPEDEF-NEXT: "spelling": " "
// TYPEDEF-NEXT: },
// TYPEDEF-NEXT: {
// TYPEDEF-NEXT: "kind": "keyword",
// TYPEDEF-NEXT: "spelling": "struct"
// TYPEDEF-NEXT: },
// TYPEDEF-NEXT: {
// TYPEDEF-NEXT: "kind": "text",
// TYPEDEF-NEXT: "spelling": " "
// TYPEDEF-NEXT: },
// TYPEDEF-NEXT: {
// TYPEDEF-NEXT: "kind": "typeIdentifier",
// TYPEDEF-NEXT: "preciseIdentifier": "c:@S@Foo",
// TYPEDEF-NEXT: "spelling": "Foo"
// TYPEDEF-NEXT: },
// TYPEDEF-NEXT: {
// TYPEDEF-NEXT: "kind": "text",
// TYPEDEF-NEXT: "spelling": " "
// TYPEDEF-NEXT: },
// TYPEDEF-NEXT: {
// TYPEDEF-NEXT: "kind": "identifier",
// TYPEDEF-NEXT: "spelling": "TypedefedFoo"
// TYPEDEF-NEXT: },
// TYPEDEF-NEXT: {
// TYPEDEF-NEXT: "kind": "text",
// TYPEDEF-NEXT: "spelling": ";"
// TYPEDEF-NEXT: }
// TYPEDEF-NEXT: ],
// TYPEDEF: "displayName": "Type Alias",
// TYPEDEF: "title": "TypedefedFoo"
// TYPEDEF: "type": "c:@S@Foo"
struct Foo {
int bar;
};
// expected-no-diagnostics
//--- reference.output.json.in
{
"metadata": {
"formatVersion": {
"major": 0,
"minor": 5,
"patch": 3
},
"generator": "?"
},
"module": {
"name": "",
"platform": {
"architecture": "arm64",
"operatingSystem": {
"minimumVersion": {
"major": 11,
"minor": 0,
"patch": 0
},
"name": "macosx"
},
"vendor": "apple"
}
},
"relationships": [
{
"kind": "memberOf",
"source": "c:@E@Test2@simple",
"target": "c:@E@Test2",
"targetFallback": "Test2"
},
{
"kind": "memberOf",
"source": "c:@S@Foo@FI@bar",
"target": "c:@S@Foo",
"targetFallback": "Foo"
}
],
"symbols": [
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "typedef"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "keyword",
"spelling": "enum"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "Test2"
},
{
"kind": "text",
"spelling": ": "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:i",
"spelling": "unsigned int"
},
{
"kind": "text",
"spelling": " { ... } "
},
{
"kind": "identifier",
"spelling": "Test2"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:@E@Test2"
},
"kind": {
"displayName": "Enumeration",
"identifier": "c.enum"
},
"location": {
"position": {
"character": 13,
"line": 3
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "Test2"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "Test2"
}
],
"title": "Test2"
},
"pathComponents": [
"Test2"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "identifier",
"spelling": "simple"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:@E@Test2@simple"
},
"kind": {
"displayName": "Enumeration Case",
"identifier": "c.enum.case"
},
"location": {
"position": {
"character": 2,
"line": 4
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "simple"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "simple"
}
],
"title": "simple"
},
"pathComponents": [
"Test2",
"simple"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "typedef"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "keyword",
"spelling": "struct"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "Test"
},
{
"kind": "text",
"spelling": " { ... } "
},
{
"kind": "identifier",
"spelling": "Test"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:@S@Test"
},
"kind": {
"displayName": "Structure",
"identifier": "c.struct"
},
"location": {
"position": {
"character": 15,
"line": 0
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "Test"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "Test"
}
],
"title": "Test"
},
"pathComponents": [
"Test"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "struct"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "Foo"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:@S@Foo"
},
"kind": {
"displayName": "Structure",
"identifier": "c.struct"
},
"location": {
"position": {
"character": 7,
"line": 9
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "Foo"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "Foo"
}
],
"title": "Foo"
},
"pathComponents": [
"Foo"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "bar"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:@S@Foo@FI@bar"
},
"kind": {
"displayName": "Instance Property",
"identifier": "c.property"
},
"location": {
"position": {
"character": 8,
"line": 10
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "bar"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "bar"
}
],
"title": "bar"
},
"pathComponents": [
"Foo",
"bar"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "typedef"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "keyword",
"spelling": "struct"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:@S@Foo",
"spelling": "Foo"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "TypedefedFoo"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:input.h@T@TypedefedFoo"
},
"kind": {
"displayName": "Type Alias",
"identifier": "c.typealias"
},
"location": {
"position": {
"character": 19,
"line": 8
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "TypedefedFoo"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "TypedefedFoo"
}
],
"title": "TypedefedFoo"
},
"pathComponents": [
"TypedefedFoo"
],
"type": "c:@S@Foo"
}
]
}

View File

@ -1,5 +1,17 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
// RUN: -x c-header %s -o - -verify | FileCheck %s
// RUN: -x c-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
// RUN: %t/output.json >> %t/output-normalized.json
// RUN: diff %t/reference.output.json %t/output-normalized.json
//--- input.h
// expected-no-diagnostics
// Global record
int _HiddenGlobal;
@ -7,22 +19,399 @@ int exposed_global;
// Record type
struct _HiddenRecord {
int HiddenRecordMember;
int a;
};
struct ExposedRecord {
int ExposedRecordMember;
int a;
};
// Typedef
typedef struct {} _HiddenTypedef;
typedef int ExposedTypedef;
typedef _HiddenTypedef ExposedTypedefToHidden;
// Macros
#define _HIDDEN_MACRO 5
#define EXPOSED_MACRO 5
// expected-no-diagnostics
// CHECK-NOT: _HiddenRecord
// CHECK-NOT: HiddenRecordMember
// CHECK: ExposedRecord
// CHECK: ExposedRecordMember
// CHECK-NOT: _HIDDEN_MACRO
// CHECK: EXPOSED_MACRO
// Symbols that start with '_' should not appear in the reference output
//--- reference.output.json.in
{
"metadata": {
"formatVersion": {
"major": 0,
"minor": 5,
"patch": 3
},
"generator": "?"
},
"module": {
"name": "",
"platform": {
"architecture": "arm64",
"operatingSystem": {
"minimumVersion": {
"major": 11,
"minor": 0,
"patch": 0
},
"name": "macosx"
},
"vendor": "apple"
}
},
"relationships": [
{
"kind": "memberOf",
"source": "c:@S@ExposedRecord@FI@a",
"target": "c:@S@ExposedRecord",
"targetFallback": "ExposedRecord"
}
],
"symbols": [
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "exposed_global"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:@exposed_global"
},
"kind": {
"displayName": "Global Variable",
"identifier": "c.var"
},
"location": {
"position": {
"character": 4,
"line": 4
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "exposed_global"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "exposed_global"
}
],
"title": "exposed_global"
},
"pathComponents": [
"exposed_global"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "struct"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "ExposedRecord"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:@S@ExposedRecord"
},
"kind": {
"displayName": "Structure",
"identifier": "c.struct"
},
"location": {
"position": {
"character": 7,
"line": 11
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "ExposedRecord"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "ExposedRecord"
}
],
"title": "ExposedRecord"
},
"pathComponents": [
"ExposedRecord"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "a"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:@S@ExposedRecord@FI@a"
},
"kind": {
"displayName": "Instance Property",
"identifier": "c.property"
},
"location": {
"position": {
"character": 6,
"line": 12
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "a"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "a"
}
],
"title": "a"
},
"pathComponents": [
"ExposedRecord",
"a"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "#define"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "EXPOSED_MACRO"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:input.h@335@macro@EXPOSED_MACRO"
},
"kind": {
"displayName": "Macro",
"identifier": "c.macro"
},
"location": {
"position": {
"character": 8,
"line": 22
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "EXPOSED_MACRO"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "EXPOSED_MACRO"
}
],
"title": "EXPOSED_MACRO"
},
"pathComponents": [
"EXPOSED_MACRO"
]
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "typedef"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:I",
"spelling": "int"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "ExposedTypedef"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:input.h@T@ExposedTypedef"
},
"kind": {
"displayName": "Type Alias",
"identifier": "c.typealias"
},
"location": {
"position": {
"character": 12,
"line": 17
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "ExposedTypedef"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "ExposedTypedef"
}
],
"title": "ExposedTypedef"
},
"pathComponents": [
"ExposedTypedef"
],
"type": "c:I"
},
{
"accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
"spelling": "typedef"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "typeIdentifier",
"preciseIdentifier": "c:@SA@_HiddenTypedef",
"spelling": "_HiddenTypedef"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "ExposedTypedefToHidden"
},
{
"kind": "text",
"spelling": ";"
}
],
"identifier": {
"interfaceLanguage": "c",
"precise": "c:input.h@T@ExposedTypedefToHidden"
},
"kind": {
"displayName": "Type Alias",
"identifier": "c.typealias"
},
"location": {
"position": {
"character": 23,
"line": 18
},
"uri": "file://INPUT_DIR/input.h"
},
"names": {
"navigator": [
{
"kind": "identifier",
"spelling": "ExposedTypedefToHidden"
}
],
"subHeading": [
{
"kind": "identifier",
"spelling": "ExposedTypedefToHidden"
}
],
"title": "ExposedTypedefToHidden"
},
"pathComponents": [
"ExposedTypedefToHidden"
],
"type": "c:@SA@_HiddenTypedef"
}
]
}

View File

@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx -x c-header\
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx -x c-header\
// RUN: %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
@ -12,7 +12,7 @@
//--- input.h
/// My Union
union Union {
union Union{
/// the a option
int a;
/// the b option

View File

@ -14,7 +14,7 @@
// RUN: %t/vfsoverlay.yaml.in >> %t/vfsoverlay.yaml
// Input headers use paths to the framework root/DSTROOT
// RUN: %clang_cc1 -extract-api --pretty-sgf -v --product-name=MyFramework \
// RUN: %clang_cc1 -extract-api -v --product-name=MyFramework \
// RUN: -triple arm64-apple-macosx \
// RUN: -iquote%t -ivfsoverlay %t/vfsoverlay.yaml -F%t/Frameworks \
// RUN: -x objective-c-header \

View File

@ -31,8 +31,6 @@ struct Foo {
- (void)derivedMethodWithValue:(id<Protocol>)value {
int a = 5;
}
/// Impl only docs
- (void)implOnlyMethod { }
@end
// RUN: c-index-test -single-symbol-sgf-at=%s:4:9 local %s | FileCheck -check-prefix=CHECK-FOO %s
@ -120,10 +118,3 @@ struct Foo {
// CHECK-DERIVED-METHOD-IMPL: "text":"Derived method docs"
// CHECK-DERIVED-METHOD-IMPL: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"}
// CHECK-DERIVED-METHOD-IMPL: "title":"derivedMethodWithValue:"
// RUN: c-index-test -single-symbol-sgf-at=%s:35:11 local %s | FileCheck -check-prefix=CHECK-IMPL-ONLY %s
// CHECK-IMPL-ONLY: "relatedSymbols":[]
// CHECK-IMPL-ONLY: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Derived(im)implOnlyMethod","target":"c:objc(cs)Derived"
// CHECK-IMPL-ONLY: "text":"Impl only docs"
// CHECK-IMPL-ONLY: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"}
// CHECK-IMPL-ONLY: "title":"implOnlyMethod"

View File

@ -18,7 +18,6 @@
#include "clang-c/Index.h"
#include "clang-c/Platform.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/ExtractAPI/API.h"
@ -55,20 +54,41 @@ struct LibClangExtractAPIVisitor
if (!shouldDeclBeIncluded(Decl))
return true;
auto *Interface = Decl->getClassInterface();
const ObjCInterfaceDecl *Interface = Decl->getClassInterface();
StringRef Name = Interface->getName();
StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
DocComment Comment;
if (auto *RawComment = fetchRawCommentForDecl(Interface))
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
Context.getDiagnostics());
if (!VisitObjCInterfaceDecl(Interface))
return false;
// Build declaration fragments and sub-heading by generating them for the
// interface.
DeclarationFragments Declaration =
DeclarationFragmentsBuilder::getFragmentsForObjCInterface(Interface);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
SmallString<128> USR;
index::generateUSRForDecl(Interface, USR);
if (auto *InterfaceRecord = dyn_cast_if_present<ObjCInterfaceRecord>(
API.findRecordForUSR(USR))) {
recordObjCMethods(InterfaceRecord, Decl->methods());
recordObjCProperties(InterfaceRecord, Decl->properties());
recordObjCInstanceVariables(InterfaceRecord, Decl->ivars());
// Collect super class information.
SymbolReference SuperClass;
if (const auto *SuperClassDecl = Decl->getSuperClass()) {
SuperClass.Name = SuperClassDecl->getObjCRuntimeNameAsString();
SuperClass.USR = API.recordUSR(SuperClassDecl);
}
ObjCInterfaceRecord *ObjCInterfaceRecord = API.addObjCInterface(
Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage,
Comment, Declaration, SubHeading, SuperClass, isInSystemHeader(Decl));
// Record all methods (selectors). This doesn't include automatically
// synthesized property methods.
recordObjCMethods(ObjCInterfaceRecord, Decl->methods());
recordObjCProperties(ObjCInterfaceRecord, Decl->properties());
recordObjCInstanceVariables(ObjCInterfaceRecord, Decl->ivars());
return true;
}
};
@ -76,14 +96,21 @@ struct LibClangExtractAPIVisitor
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(APISet, CXAPISet)
// Visits the Decl D and it's transitive DeclContexts recursively, starting from
// the outer-most context. This is guaranteed to visit every Decl we need in the
// right order to generate symbol graph information for D.
static void WalkupFromMostDerivedType(LibClangExtractAPIVisitor &Visitor,
Decl *D);
template <typename DeclTy>
static bool WalkupParentContext(DeclContext *Parent,
LibClangExtractAPIVisitor &Visitor) {
if (auto *D = dyn_cast<DeclTy>(Parent)) {
WalkupFromMostDerivedType(Visitor, D);
return true;
}
return false;
}
static void WalkupFromMostDerivedType(LibClangExtractAPIVisitor &Visitor,
Decl *D) {
if (auto *Parent = D->getDeclContext())
WalkupFromMostDerivedType(Visitor, cast<Decl>(Parent));
switch (D->getKind()) {
#define ABSTRACT_DECL(DECL)
#define DECL(CLASS, BASE) \
@ -92,12 +119,20 @@ static void WalkupFromMostDerivedType(LibClangExtractAPIVisitor &Visitor,
break;
#include "clang/AST/DeclNodes.inc"
}
for (auto *Parent = D->getDeclContext(); Parent != nullptr;
Parent = Parent->getParent()) {
if (WalkupParentContext<ObjCContainerDecl>(Parent, Visitor))
return;
if (WalkupParentContext<TagDecl>(Parent, Visitor))
return;
}
}
static CXString GenerateCXStringFromSymbolGraphData(llvm::json::Object Obj) {
llvm::SmallString<0> BackingString;
llvm::raw_svector_ostream OS(BackingString);
OS << llvm::formatv("{0}", Value(std::move(Obj)));
OS << Value(std::move(Obj));
return cxstring::createDup(BackingString.str());
}