| //===--- ModuleAnaluzerNodes.h - Nodes for API differ tool ---------------====// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // Describing nodes from a swiftmodule file to detect ABI/API breakages. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef __SWIFT_ABI_DIGESTER_MODULE_NODES_H__ |
| #define __SWIFT_ABI_DIGESTER_MODULE_NODES_H__ |
| |
| #include "clang/AST/ASTContext.h" |
| #include "clang/AST/DeclObjC.h" |
| #include "clang/Lex/Preprocessor.h" |
| #include "clang/Sema/Lookup.h" |
| #include "clang/Sema/Sema.h" |
| #include "llvm/ADT/TinyPtrVector.h" |
| #include "llvm/Support/CommandLine.h" |
| #include "llvm/Support/Compiler.h" |
| #include "llvm/Support/FileSystem.h" |
| #include "llvm/Support/MemoryBuffer.h" |
| #include "llvm/Support/Path.h" |
| #include "llvm/Support/Signals.h" |
| #include "llvm/Support/YAMLParser.h" |
| #include "llvm/Support/YAMLTraits.h" |
| #include "swift/AST/Attr.h" |
| #include "swift/AST/Decl.h" |
| #include "swift/AST/NameLookup.h" |
| #include "swift/AST/PrettyStackTrace.h" |
| #include "swift/AST/USRGeneration.h" |
| #include "swift/AST/GenericSignature.h" |
| #include "swift/AST/ProtocolConformance.h" |
| #include "swift/Basic/ColorUtils.h" |
| #include "swift/Basic/JSONSerialization.h" |
| #include "swift/Basic/LLVMInitialize.h" |
| #include "swift/Basic/STLExtras.h" |
| #include "swift/Basic/Version.h" |
| #include "swift/ClangImporter/ClangImporter.h" |
| #include "swift/Frontend/Frontend.h" |
| #include "swift/Frontend/PrintingDiagnosticConsumer.h" |
| #include "swift/IDE/Utils.h" |
| #include "swift/IDE/APIDigesterData.h" |
| #include <functional> |
| |
| namespace swift { |
| namespace json { |
| class Output; |
| } |
| namespace ide { |
| namespace api { |
| |
| class SDKNode; |
| typedef SDKNode* NodePtr; |
| typedef std::map<NodePtr, NodePtr> ParentMap; |
| typedef std::map<NodePtr, NodePtr> NodeMap; |
| typedef std::vector<NodePtr> NodeVector; |
| typedef std::vector<CommonDiffItem> DiffVector; |
| typedef std::vector<TypeMemberDiffItem> TypeMemberDiffVector; |
| typedef llvm::MapVector<NodePtr, NodePtr> NodePairVector; |
| |
| // The interface used to visit the SDK tree. |
| class SDKNodeVisitor { |
| friend SDKNode; |
| protected: |
| NodeVector Ancestors; |
| virtual void visit(NodePtr Node) = 0; |
| |
| NodePtr parent() { |
| if (Ancestors.empty()) |
| return nullptr; |
| return Ancestors.back(); |
| } |
| |
| int depth() { |
| return Ancestors.size() + 1; |
| } |
| public: |
| virtual ~SDKNodeVisitor() = default; |
| }; |
| |
| enum class NodeMatchReason: uint8_t { |
| |
| // Two nodes are matched because they're both roots. |
| Root, |
| |
| // The first node is missing. |
| Added, |
| |
| // The second node is missing. |
| Removed, |
| |
| // The nodes are considered a pair becuase they have same/similar name. |
| Name, |
| |
| // The nodes are matched because they're in the same order, e.g. ith child of |
| // a type declaration. |
| Sequential, |
| |
| // The first node is a function and it chanaged to a propery as the second |
| // node. |
| FuncToProperty, |
| |
| // The first node is a global variable and the second node is an enum element. |
| ModernizeEnum, |
| |
| // The first node is a type declaration and the second node is a type alias |
| // of another type declaration. |
| TypeToTypeAlias, |
| }; |
| |
| // This map keeps track of updated nodes; thus we can conveniently find out what |
| // is the counterpart of a node before or after being updated. |
| class UpdatedNodesMap { |
| NodePairVector MapImpl; |
| UpdatedNodesMap(const UpdatedNodesMap& that) = delete; |
| public: |
| UpdatedNodesMap() = default; |
| NodePtr findUpdateCounterpart(const SDKNode *Node) const; |
| void insert(NodePtr Left, NodePtr Right) { |
| assert(Left && Right && "Not update operation."); |
| MapImpl.insert({Left, Right}); |
| } |
| }; |
| |
| // Describing some attributes with ABI/API impact. The addition or removal of these |
| // attributes is considerred breakage. |
| struct BreakingAttributeInfo { |
| const DeclAttrKind Kind; |
| const StringRef Content; |
| }; |
| |
| struct CheckerOptions { |
| bool AvoidLocation; |
| bool ABI; |
| bool Verbose; |
| bool AbortOnModuleLoadFailure; |
| bool PrintModule; |
| bool SwiftOnly; |
| StringRef LocationFilter; |
| }; |
| |
| class SDKContext { |
| llvm::StringSet<> TextData; |
| llvm::BumpPtrAllocator Allocator; |
| SourceManager SourceMgr; |
| DiagnosticEngine Diags; |
| UpdatedNodesMap UpdateMap; |
| NodeMap TypeAliasUpdateMap; |
| NodeMap RevertTypeAliasUpdateMap; |
| TypeMemberDiffVector TypeMemberDiffs; |
| |
| CheckerOptions Opts; |
| std::vector<BreakingAttributeInfo> BreakingAttrs; |
| /// This is to cache the equal comparison results between nodes. |
| llvm::DenseMap<const SDKNode*, llvm::DenseMap<const SDKNode*, bool>> EqualCache; |
| |
| public: |
| SDKContext(CheckerOptions Options); |
| llvm::BumpPtrAllocator &allocator() { |
| return Allocator; |
| } |
| StringRef buffer(StringRef Text) { |
| return TextData.insert(Text).first->getKey(); |
| } |
| UpdatedNodesMap &getNodeUpdateMap() { |
| return UpdateMap; |
| } |
| NodeMap &getTypeAliasUpdateMap() { |
| return TypeAliasUpdateMap; |
| } |
| NodeMap &getRevertTypeAliasUpdateMap() { |
| return RevertTypeAliasUpdateMap; |
| } |
| TypeMemberDiffVector &getTypeMemberDiffs() { |
| return TypeMemberDiffs; |
| } |
| SourceManager &getSourceMgr() { |
| return SourceMgr; |
| } |
| DiagnosticEngine &getDiags() { |
| return Diags; |
| } |
| bool isEqual(const SDKNode &Left, const SDKNode &Right); |
| bool checkingABI() const { return Opts.ABI; } |
| AccessLevel getAccessLevel(const ValueDecl *VD) const; |
| const CheckerOptions &getOpts() const { return Opts; } |
| bool shouldIgnore(Decl *D, const Decl* Parent = nullptr) const; |
| ArrayRef<BreakingAttributeInfo> getBreakingAttributeInfo() const { return BreakingAttrs; } |
| Optional<uint8_t> getFixedBinaryOrder(ValueDecl *VD) const; |
| template<class YAMLNodeTy, typename ...ArgTypes> |
| void diagnose(YAMLNodeTy node, Diag<ArgTypes...> ID, |
| typename detail::PassArgument<ArgTypes>::type... args) { |
| auto smRange = node->getSourceRange(); |
| auto range = SourceRange(SourceLoc(smRange.Start), SourceLoc(smRange.End)); |
| Diags.diagnose(range.Start, ID, std::forward<ArgTypes>(args)...) |
| .highlight(range); |
| } |
| }; |
| |
| enum class KnownTypeKind: uint8_t { |
| #define KNOWN_TYPE(NAME) NAME, |
| #include "swift/IDE/DigesterEnums.def" |
| Unknown, |
| }; |
| |
| enum class KnownProtocolKind: uint8_t { |
| #define KNOWN_PROTOCOL(NAME) NAME, |
| #include "swift/IDE/DigesterEnums.def" |
| }; |
| |
| class SDKNodeRoot; |
| class SDKNodeDeclGetter; |
| class SDKNodeDeclSetter; |
| struct SDKNodeInitInfo; |
| |
| class SDKNode { |
| typedef std::vector<SDKNode*>::iterator ChildIt; |
| protected: |
| SDKContext &Ctx; |
| StringRef Name; |
| StringRef PrintedName; |
| unsigned TheKind : 4; |
| NodeVector Children; |
| std::set<NodeAnnotation> Annotations; |
| std::map<NodeAnnotation, StringRef> AnnotateComments; |
| NodePtr Parent = nullptr; |
| protected: |
| SDKNode(SDKNodeInitInfo Info, SDKNodeKind Kind); |
| virtual ~SDKNode() = default; |
| public: |
| static SDKNode *constructSDKNode(SDKContext &Ctx, llvm::yaml::MappingNode *Node); |
| static void preorderVisit(NodePtr Root, SDKNodeVisitor &Visitor); |
| static void postorderVisit(NodePtr Root, SDKNodeVisitor &Visitor); |
| |
| bool operator==(const SDKNode &Other) const; |
| bool operator!=(const SDKNode &Other) const { return !((*this) == Other); } |
| void output(json::Output &out, KeyKind Key, bool Value); |
| void output(json::Output &out, KeyKind Key, StringRef Value); |
| |
| ArrayRef<NodeAnnotation> |
| getAnnotations(std::vector<NodeAnnotation> &Scratch) const; |
| bool isLeaf() const { return Children.empty(); } |
| SDKNodeKind getKind() const { return SDKNodeKind(TheKind); } |
| StringRef getName() const { return Name; } |
| bool isNameValid() const { return Name != "_"; } |
| StringRef getPrintedName() const { return PrintedName; } |
| void removeChild(ChildIt CI) { Children.erase(CI); } |
| ChildIt getChildBegin() { return Children.begin(); } |
| void annotate(NodeAnnotation Anno) { Annotations.insert(Anno); } |
| void annotate(NodeAnnotation Anno, StringRef Comment); |
| void removeAnnotate(NodeAnnotation Anno); |
| NodePtr getParent() const { return Parent; }; |
| unsigned getChildrenCount() const { return Children.size(); } |
| NodePtr childAt(unsigned I) const; |
| void removeChild(NodePtr C); |
| StringRef getAnnotateComment(NodeAnnotation Anno) const; |
| bool isAnnotatedAs(NodeAnnotation Anno) const; |
| void addChild(SDKNode *Child); |
| NodeVector& getChildren() { return Children; } |
| ArrayRef<SDKNode*> getChildren() const { return Children; } |
| bool hasSameChildren(const SDKNode &Other) const; |
| unsigned getChildIndex(const SDKNode *Child) const; |
| SDKNode* getOnlyChild() const; |
| SDKContext &getSDKContext() const { return Ctx; } |
| SDKNodeRoot *getRootNode() const; |
| virtual void jsonize(json::Output &Out); |
| virtual void diagnose(SDKNode *Right) {}; |
| template <typename T> const T *getAs() const { |
| if (T::classof(this)) |
| return static_cast<const T*>(this); |
| llvm_unreachable("incompatible types"); |
| } |
| template <typename T> T *getAs() { |
| if (T::classof(this)) |
| return static_cast<T*>(this); |
| llvm_unreachable("incompatible types"); |
| } |
| }; |
| |
| class SDKNodeDecl: public SDKNode { |
| DeclKind DKind; |
| StringRef Usr; |
| StringRef Location; |
| StringRef ModuleName; |
| std::vector<DeclAttrKind> DeclAttributes; |
| bool IsImplicit; |
| bool IsStatic; |
| bool IsDeprecated; |
| bool IsProtocolReq; |
| bool IsOverriding; |
| bool IsOpen; |
| bool IsInternal; |
| uint8_t ReferenceOwnership; |
| StringRef GenericSig; |
| Optional<uint8_t> FixedBinaryOrder; |
| |
| protected: |
| SDKNodeDecl(SDKNodeInitInfo Info, SDKNodeKind Kind); |
| virtual ~SDKNodeDecl() = default; |
| public: |
| StringRef getUsr() const { return Usr; } |
| StringRef getLocation() const { return Location; } |
| StringRef getModuleName() const {return ModuleName;} |
| StringRef getHeaderName() const; |
| ArrayRef<DeclAttrKind> getDeclAttributes() const; |
| bool hasAttributeChange(const SDKNodeDecl &Another) const; |
| swift::ReferenceOwnership getReferenceOwnership() const { |
| return swift::ReferenceOwnership(ReferenceOwnership); |
| } |
| bool isObjc() const { return Usr.startswith("c:"); } |
| static bool classof(const SDKNode *N); |
| DeclKind getDeclKind() const { return DKind; } |
| void printFullyQualifiedName(llvm::raw_ostream &OS) const; |
| StringRef getFullyQualifiedName() const; |
| bool isDeprecated() const { return IsDeprecated; }; |
| bool isProtocolRequirement() const { return IsProtocolReq; } |
| bool isNonOptionalProtocolRequirement() const; |
| bool hasDeclAttribute(DeclAttrKind DAKind) const; |
| bool isImplicit() const { return IsImplicit; }; |
| bool isStatic() const { return IsStatic; }; |
| bool isOverriding() const { return IsOverriding; }; |
| bool isOptional() const { return hasDeclAttribute(DeclAttrKind::DAK_Optional); } |
| bool isOpen() const { return IsOpen; } |
| bool isInternal() const { return IsInternal; } |
| StringRef getGenericSignature() const { return GenericSig; } |
| StringRef getScreenInfo() const; |
| bool hasFixedBinaryOrder() const { return FixedBinaryOrder.hasValue(); } |
| uint8_t getFixedBinaryOrder() const { return *FixedBinaryOrder; } |
| virtual void jsonize(json::Output &Out) override; |
| virtual void diagnose(SDKNode *Right) override; |
| }; |
| |
| class SDKNodeRoot: public SDKNode { |
| /// This keeps track of all decl descendants with USRs. |
| llvm::StringMap<llvm::SmallSetVector<SDKNodeDecl*, 2>> DescendantDeclTable; |
| |
| public: |
| SDKNodeRoot(SDKNodeInitInfo Info); |
| static SDKNode *getInstance(SDKContext &Ctx); |
| static bool classof(const SDKNode *N); |
| void registerDescendant(SDKNode *D); |
| ArrayRef<SDKNodeDecl*> getDescendantsByUsr(StringRef Usr) { |
| return DescendantDeclTable[Usr].getArrayRef(); |
| } |
| }; |
| |
| class SDKNodeType: public SDKNode { |
| std::vector<TypeAttrKind> TypeAttributes; |
| bool HasDefaultArg; |
| |
| // Empty() implies "Default" |
| StringRef ParamValueOwnership; |
| |
| protected: |
| SDKNodeType(SDKNodeInitInfo Info, SDKNodeKind Kind); |
| ~SDKNodeType() = default; |
| public: |
| bool hasTypeAttribute(TypeAttrKind DAKind) const; |
| KnownTypeKind getTypeKind() const; |
| void addTypeAttribute(TypeAttrKind AttrKind); |
| ArrayRef<TypeAttrKind> getTypeAttributes() const; |
| SDKNodeDecl *getClosestParentDecl() const; |
| |
| // When the type node represents a function parameter, this function returns |
| // whether the parameter has a default value. |
| bool hasDefaultArgument() const { return HasDefaultArg; } |
| bool isTopLevelType() const { return !isa<SDKNodeType>(getParent()); } |
| StringRef getTypeRoleDescription() const; |
| StringRef getParamValueOwnership() const; |
| static bool classof(const SDKNode *N); |
| virtual void jsonize(json::Output &Out) override; |
| virtual void diagnose(SDKNode *Right) override; |
| bool hasAttributeChange(const SDKNodeType &Another) const; |
| }; |
| |
| class SDKNodeTypeNominal : public SDKNodeType { |
| StringRef USR; |
| public: |
| SDKNodeTypeNominal(SDKNodeInitInfo Info); |
| // Get the usr of the correspoding nominal type decl. |
| StringRef getUsr() const { return USR; } |
| static bool classof(const SDKNode *N); |
| void jsonize(json::Output &Out) override; |
| }; |
| |
| class SDKNodeTypeFunc : public SDKNodeType { |
| public: |
| SDKNodeTypeFunc(SDKNodeInitInfo Info); |
| bool isEscaping() const { return hasTypeAttribute(TypeAttrKind::TAK_noescape); } |
| static bool classof(const SDKNode *N); |
| void diagnose(SDKNode *Right) override; |
| }; |
| |
| class SDKNodeTypeAlias : public SDKNodeType { |
| public: |
| SDKNodeTypeAlias(SDKNodeInitInfo Info); |
| const SDKNodeType *getUnderlyingType() const { |
| return getOnlyChild()->getAs<SDKNodeType>(); |
| } |
| static bool classof(const SDKNode *N); |
| }; |
| |
| class SDKNodeVectorViewer { |
| ArrayRef<SDKNode*> Collection; |
| llvm::function_ref<bool(NodePtr)> Selector; |
| typedef ArrayRef<SDKNode*>::iterator VectorIt; |
| VectorIt getNext(VectorIt Start); |
| class ViewerIterator; |
| |
| public: |
| SDKNodeVectorViewer(ArrayRef<SDKNode*> Collection, |
| llvm::function_ref<bool(NodePtr)> Selector) : |
| Collection(Collection), |
| Selector(Selector) {} |
| ViewerIterator begin(); |
| ViewerIterator end(); |
| }; |
| |
| class SDKNodeVectorViewer::ViewerIterator : |
| public std::iterator<std::input_iterator_tag, VectorIt> { |
| SDKNodeVectorViewer &Viewer; |
| VectorIt P; |
| public: |
| ViewerIterator(SDKNodeVectorViewer &Viewer, VectorIt P) : Viewer(Viewer), P(P) {} |
| ViewerIterator(const ViewerIterator& mit) : Viewer(mit.Viewer), P(mit.P) {} |
| ViewerIterator& operator++(); |
| ViewerIterator operator++(int) {ViewerIterator tmp(*this); operator++(); return tmp;} |
| bool operator==(const ViewerIterator& rhs) {return P==rhs.P;} |
| bool operator!=(const ViewerIterator& rhs) {return P!=rhs.P;} |
| const NodePtr& operator*() {return *P;} |
| }; |
| |
| class SDKNodeDeclType: public SDKNodeDecl { |
| StringRef SuperclassUsr; |
| std::vector<StringRef> SuperclassNames; |
| std::vector<SDKNode*> Conformances; |
| StringRef EnumRawTypeName; |
| public: |
| SDKNodeDeclType(SDKNodeInitInfo Info); |
| static bool classof(const SDKNode *N); |
| StringRef getSuperClassUsr() const { return SuperclassUsr; } |
| ArrayRef<StringRef> getClassInheritanceChain() const { return SuperclassNames; } |
| void addConformance(SDKNode *Conf); |
| ArrayRef<SDKNode*> getConformances() const { return Conformances; } |
| NodeVector getConformances() { return Conformances; } |
| StringRef getSuperClassName() const { |
| return SuperclassNames.empty() ? StringRef() : SuperclassNames.front(); |
| }; |
| |
| #define NOMINAL_TYPE_DECL(ID, PARENT) \ |
| bool is##ID() const { return getDeclKind() == DeclKind::ID; } |
| #define DECL(ID, PARENT) |
| #include "swift/AST/DeclNodes.def" |
| |
| StringRef getEnumRawTypeName() const { |
| assert(isEnum()); |
| return EnumRawTypeName; |
| } |
| |
| Optional<SDKNodeDeclType*> getSuperclass() const; |
| |
| /// Finding the node through all children, including the inheritted ones, |
| /// whose printed name matches with the given name. |
| Optional<SDKNodeDecl*> lookupChildByPrintedName(StringRef Name) const; |
| SDKNodeType *getRawValueType() const; |
| bool isConformingTo(KnownProtocolKind Kind) const; |
| void jsonize(json::Output &out) override; |
| void diagnose(SDKNode *Right) override; |
| }; |
| |
| /// Keeps track of a conformance; the children of this node are |
| /// SDKNodeTypeWitness. The conformance node should have no parent since |
| /// they are stored as an additional property in SDKNodeDeclType. |
| /// The SDKNode part of the conformance node is constructed using the protocol |
| /// in the conformance, thus getName() will give us the name of the protocol. |
| class SDKNodeConformance: public SDKNode { |
| SDKNodeDeclType *TypeDecl; |
| friend class SDKNodeDeclType; |
| public: |
| SDKNodeConformance(SDKNodeInitInfo Info); |
| ArrayRef<SDKNode*> getTypeWitnesses() const { return Children; } |
| SDKNodeDeclType *getNominalTypeDecl() const { return TypeDecl; } |
| static bool classof(const SDKNode *N); |
| }; |
| |
| /// Keep track of a type witness of an associated type requirement. These nodes |
| /// only appear as children of SDKNodeConformance. |
| /// The SDKNode part of this node is constructed using the associated type decl; |
| /// thus getName() will give us the name of the associated type. The only child |
| /// of this node is a type node witnessing the associated type requirement. |
| class SDKNodeTypeWitness: public SDKNode { |
| public: |
| SDKNodeTypeWitness(SDKNodeInitInfo Info); |
| StringRef getWitnessedTypeName() const; |
| SDKNodeType *getUnderlyingType() const; |
| static bool classof(const SDKNode *N); |
| }; |
| |
| class SDKNodeDeclOperator : public SDKNodeDecl { |
| public: |
| SDKNodeDeclOperator(SDKNodeInitInfo Info); |
| static bool classof(const SDKNode *N); |
| void diagnose(SDKNode *Right) override; |
| }; |
| |
| class SDKNodeDeclTypeAlias : public SDKNodeDecl { |
| public: |
| SDKNodeDeclTypeAlias(SDKNodeInitInfo Info); |
| const SDKNodeType* getUnderlyingType() const { |
| return getOnlyChild()->getAs<SDKNodeType>(); |
| } |
| static bool classof(const SDKNode *N); |
| }; |
| |
| class SDKNodeDeclAssociatedType: public SDKNodeDecl { |
| public: |
| SDKNodeDeclAssociatedType(SDKNodeInitInfo Info); |
| const SDKNodeType* getDefault() const { |
| return getChildrenCount() ? getOnlyChild()->getAs<SDKNodeType>(): nullptr; |
| } |
| static bool classof(const SDKNode *N); |
| }; |
| |
| class SDKNodeDeclVar : public SDKNodeDecl { |
| bool IsLet; |
| bool HasStorage; |
| bool HasDidSet; |
| bool HasWillSet; |
| public: |
| SDKNodeDeclVar(SDKNodeInitInfo Info); |
| static bool classof(const SDKNode *N); |
| SDKNodeDeclGetter *getGetter() const; |
| SDKNodeDeclSetter *getSetter() const; |
| SDKNodeType *getType() const; |
| bool isLet() const { return IsLet; } |
| void jsonize(json::Output &Out) override; |
| void diagnose(SDKNode *Right) override; |
| bool hasStorage() const { return HasStorage; } |
| bool hasDidSet() const { return HasDidSet; } |
| bool hasWillSet() const { return HasWillSet; } |
| }; |
| |
| class SDKNodeDeclAbstractFunc : public SDKNodeDecl { |
| bool IsThrowing; |
| Optional<uint8_t> SelfIndex; |
| |
| protected: |
| SDKNodeDeclAbstractFunc(SDKNodeInitInfo Info, SDKNodeKind Kind); |
| virtual ~SDKNodeDeclAbstractFunc() = default; |
| public: |
| bool isThrowing() const { return IsThrowing; } |
| uint8_t getSelfIndex() const { return SelfIndex.getValue(); } |
| Optional<uint8_t> getSelfIndexOptional() const { return SelfIndex; } |
| bool hasSelfIndex() const { return SelfIndex.hasValue(); } |
| static bool classof(const SDKNode *N); |
| virtual void jsonize(json::Output &out) override; |
| static StringRef getTypeRoleDescription(SDKContext &Ctx, unsigned Index); |
| virtual void diagnose(SDKNode *Right) override; |
| }; |
| |
| class SDKNodeDeclSubscript: public SDKNodeDeclAbstractFunc { |
| bool HasSetter; |
| bool HasStorage; |
| bool HasDidSet; |
| bool HasWillSet; |
| public: |
| SDKNodeDeclSubscript(SDKNodeInitInfo Info); |
| static bool classof(const SDKNode *N); |
| bool hasSetter() const { return HasSetter; } |
| bool hasStorage() const { return HasStorage; } |
| void jsonize(json::Output &Out) override; |
| void diagnose(SDKNode *Right) override; |
| bool hasDidSet() const { return HasDidSet; } |
| bool hasWillSet() const { return HasWillSet; } |
| }; |
| |
| class SDKNodeDeclFunction: public SDKNodeDeclAbstractFunc { |
| StringRef FuncSelfKind; |
| public: |
| SDKNodeDeclFunction(SDKNodeInitInfo Info); |
| SDKNode *getReturnType() { return *getChildBegin(); } |
| StringRef getSelfAccessKind() const { return FuncSelfKind; } |
| static bool classof(const SDKNode *N); |
| void jsonize(json::Output &Out) override; |
| void diagnose(SDKNode *Right) override; |
| }; |
| |
| class SDKNodeDeclConstructor: public SDKNodeDeclAbstractFunc { |
| public: |
| SDKNodeDeclConstructor(SDKNodeInitInfo Info); |
| static bool classof(const SDKNode *N); |
| }; |
| |
| class SDKNodeDeclGetter: public SDKNodeDeclAbstractFunc { |
| public: |
| SDKNodeDeclGetter(SDKNodeInitInfo Info); |
| static bool classof(const SDKNode *N); |
| }; |
| |
| class SDKNodeDeclSetter: public SDKNodeDeclAbstractFunc { |
| public: |
| SDKNodeDeclSetter(SDKNodeInitInfo Info); |
| static bool classof(const SDKNode *N); |
| }; |
| |
| // The additional information we need for a type node in the digest. |
| // We use type node to represent entities more than types, e.g. parameters, so |
| // this struct is necessary to pass down to create a type node. |
| struct TypeInitInfo { |
| bool IsImplicitlyUnwrappedOptional = false; |
| bool hasDefaultArgument = false; |
| StringRef ValueOwnership; |
| }; |
| |
| class SwiftDeclCollector: public VisibleDeclConsumer { |
| SDKContext &Ctx; |
| std::vector<std::unique_ptr<llvm::MemoryBuffer>> OwnedBuffers; |
| SDKNode *RootNode; |
| llvm::SetVector<Decl*> KnownDecls; |
| // Collected and sorted after we get all of them. |
| std::vector<ValueDecl *> ClangMacros; |
| std::set<ExtensionDecl*> HandledExtensions; |
| public: |
| void visitAllRoots(SDKNodeVisitor &Visitor) { |
| SDKNode::preorderVisit(RootNode, Visitor); |
| } |
| SwiftDeclCollector(SDKContext &Ctx) : Ctx(Ctx), |
| RootNode(SDKNodeRoot::getInstance(Ctx)) {} |
| |
| // Construct all roots vector from a given file where a forest was |
| // previously dumped. |
| void deSerialize(StringRef Filename); |
| |
| // Serialize the content of all roots to a given file using JSON format. |
| void serialize(StringRef Filename); |
| |
| // After collecting decls, either from imported modules or from a previously |
| // serialized JSON file, using this function to get the root of the SDK. |
| SDKNodeRoot* getSDKRoot() { return static_cast<SDKNodeRoot*>(RootNode); } |
| |
| void printTopLevelNames(); |
| |
| void addConformancesToTypeDecl(SDKNodeDeclType *Root, NominalTypeDecl* NTD); |
| void addMembersToRoot(SDKNode *Root, IterableDeclContext *Context); |
| |
| SDKNode *constructTypeWitnessNode(AssociatedTypeDecl *Assoc, Type Ty); |
| SDKNode *constructConformanceNode(ProtocolConformance *Conform); |
| SDKNode *constructSubscriptDeclNode(SubscriptDecl *SD); |
| SDKNode *constructAssociatedTypeNode(AssociatedTypeDecl *ATD); |
| SDKNode *constructTypeAliasNode(TypeAliasDecl *TAD); |
| SDKNode *constructVarNode(ValueDecl *VD); |
| SDKNode *constructExternalExtensionNode(NominalTypeDecl *NTD, |
| ArrayRef<ExtensionDecl*> AllExts); |
| SDKNode *constructTypeDeclNode(NominalTypeDecl *NTD); |
| SDKNode *constructInitNode(ConstructorDecl *CD); |
| SDKNode *constructFunctionNode(FuncDecl* FD, SDKNodeKind Kind); |
| SDKNode *constructOperatorDeclNode(OperatorDecl *OD); |
| std::vector<SDKNode*> createParameterNodes(ParameterList *PL); |
| SDKNode *constructTypeNode(Type T, TypeInitInfo Info = TypeInitInfo()); |
| void processValueDecl(ValueDecl *VD); |
| void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason) override; |
| void processDecl(Decl *D); |
| public: |
| void lookupVisibleDecls(ArrayRef<ModuleDecl *> Modules); |
| }; |
| |
| int dumpSwiftModules(const CompilerInvocation &InitInvok, |
| const llvm::StringSet<> &ModuleNames, |
| StringRef OutputDir, |
| const std::vector<std::string> PrintApis, |
| CheckerOptions Opts); |
| |
| int dumpSDKContent(const CompilerInvocation &InitInvok, |
| const llvm::StringSet<> &ModuleNames, |
| StringRef OutputFile, CheckerOptions Opts); |
| |
| /// Mostly for testing purposes, this function de-serializes the SDK dump in |
| /// dumpPath and re-serialize them to OutputPath. If the tool performs correctly, |
| /// the contents in dumpPath and OutputPath should be identical. |
| int deserializeSDKDump(StringRef dumpPath, StringRef OutputPath, |
| CheckerOptions Opts); |
| |
| int findDeclUsr(StringRef dumpPath, CheckerOptions Opts); |
| |
| void nodeSetDifference(ArrayRef<SDKNode*> Left, ArrayRef<SDKNode*> Right, |
| NodeVector &LeftMinusRight, NodeVector &RightMinusLeft); |
| |
| } // end of abi namespace |
| } // end of ide namespace |
| } // end of Swift namespace |
| |
| #endif |