//===--- SwiftLangSupport.cpp ---------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #include "SwiftLangSupport.h" #include "SwiftASTManager.h" #include "SourceKit/Core/Context.h" #include "SourceKit/Support/UIdent.h" #include "swift/AST/AST.h" #include "swift/AST/ASTVisitor.h" #include "swift/AST/USRGeneration.h" #include "swift/IDE/CodeCompletion.h" #include "swift/IDE/CodeCompletionCache.h" #include "swift/IDE/SyntaxModel.h" #include "swift/IDE/Utils.h" #include "swift/Config.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/Hashing.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include using namespace SourceKit; using namespace swift; using namespace swift::ide; static UIdent KindDeclFunctionFree("source.lang.swift.decl.function.free"); static UIdent KindRefFunctionFree("source.lang.swift.ref.function.free"); static UIdent KindDeclMethodInstance( "source.lang.swift.decl.function.method.instance"); static UIdent KindRefMethodInstance( "source.lang.swift.ref.function.method.instance"); static UIdent KindDeclMethodStatic( "source.lang.swift.decl.function.method.static"); static UIdent KindRefMethodStatic( "source.lang.swift.ref.function.method.static"); static UIdent KindDeclMethodClass( "source.lang.swift.decl.function.method.class"); static UIdent KindRefMethodClass( "source.lang.swift.ref.function.method.class"); static UIdent KindDeclAccessorGetter( "source.lang.swift.decl.function.accessor.getter"); static UIdent KindRefAccessorGetter( "source.lang.swift.ref.function.accessor.getter"); static UIdent KindDeclAccessorSetter( "source.lang.swift.decl.function.accessor.setter"); static UIdent KindRefAccessorSetter( "source.lang.swift.ref.function.accessor.setter"); static UIdent KindDeclAccessorWillSet( "source.lang.swift.decl.function.accessor.willset"); static UIdent KindRefAccessorWillSet( "source.lang.swift.ref.function.accessor.willset"); static UIdent KindDeclAccessorDidSet( "source.lang.swift.decl.function.accessor.didset"); static UIdent KindRefAccessorDidSet( "source.lang.swift.ref.function.accessor.didset"); static UIdent KindDeclAccessorAddress( "source.lang.swift.decl.function.accessor.address"); static UIdent KindRefAccessorAddress( "source.lang.swift.ref.function.accessor.address"); static UIdent KindDeclAccessorMutableAddress( "source.lang.swift.decl.function.accessor.mutableaddress"); static UIdent KindRefAccessorMutableAddress( "source.lang.swift.ref.function.accessor.mutableaddress"); static UIdent KindDeclConstructor("source.lang.swift.decl.function.constructor"); static UIdent KindRefConstructor("source.lang.swift.ref.function.constructor"); static UIdent KindDeclDestructor("source.lang.swift.decl.function.destructor"); static UIdent KindRefDestructor("source.lang.swift.ref.function.destructor"); static UIdent KindDeclFunctionPrefixOperator("source.lang.swift.decl.function.operator.prefix"); static UIdent KindDeclFunctionPostfixOperator("source.lang.swift.decl.function.operator.postfix"); static UIdent KindDeclFunctionInfixOperator("source.lang.swift.decl.function.operator.infix"); static UIdent KindRefFunctionPrefixOperator("source.lang.swift.ref.function.operator.prefix"); static UIdent KindRefFunctionPostfixOperator("source.lang.swift.ref.function.operator.postfix"); static UIdent KindRefFunctionInfixOperator("source.lang.swift.ref.function.operator.infix"); static UIdent KindDeclSubscript("source.lang.swift.decl.function.subscript"); static UIdent KindRefSubscript("source.lang.swift.ref.function.subscript"); static UIdent KindDeclVarGlobal("source.lang.swift.decl.var.global"); static UIdent KindRefVarGlobal("source.lang.swift.ref.var.global"); static UIdent KindDeclVarInstance("source.lang.swift.decl.var.instance"); static UIdent KindRefVarInstance("source.lang.swift.ref.var.instance"); static UIdent KindDeclVarStatic("source.lang.swift.decl.var.static"); static UIdent KindRefVarStatic("source.lang.swift.ref.var.static"); static UIdent KindDeclVarClass("source.lang.swift.decl.var.class"); static UIdent KindRefVarClass("source.lang.swift.ref.var.class"); static UIdent KindDeclVarLocal("source.lang.swift.decl.var.local"); static UIdent KindRefVarLocal("source.lang.swift.ref.var.local"); static UIdent KindDeclVarParam("source.lang.swift.decl.var.parameter"); static UIdent KindDeclModule("source.lang.swift.decl.module"); static UIdent KindDeclClass("source.lang.swift.decl.class"); static UIdent KindRefClass("source.lang.swift.ref.class"); static UIdent KindDeclStruct("source.lang.swift.decl.struct"); static UIdent KindRefStruct("source.lang.swift.ref.struct"); static UIdent KindDeclEnum("source.lang.swift.decl.enum"); static UIdent KindRefEnum("source.lang.swift.ref.enum"); static UIdent KindDeclEnumCase("source.lang.swift.decl.enumcase"); static UIdent KindDeclEnumElement("source.lang.swift.decl.enumelement"); static UIdent KindRefEnumElement("source.lang.swift.ref.enumelement"); static UIdent KindDeclProtocol("source.lang.swift.decl.protocol"); static UIdent KindRefProtocol("source.lang.swift.ref.protocol"); static UIdent KindDeclExtension("source.lang.swift.decl.extension"); static UIdent KindDeclExtensionStruct("source.lang.swift.decl.extension.struct"); static UIdent KindDeclExtensionClass("source.lang.swift.decl.extension.class"); static UIdent KindDeclExtensionEnum("source.lang.swift.decl.extension.enum"); static UIdent KindDeclExtensionProtocol("source.lang.swift.decl.extension.protocol"); static UIdent KindDeclAssociatedType("source.lang.swift.decl.associatedtype"); static UIdent KindRefAssociatedType("source.lang.swift.ref.associatedtype"); static UIdent KindDeclTypeAlias("source.lang.swift.decl.typealias"); static UIdent KindRefTypeAlias("source.lang.swift.ref.typealias"); static UIdent KindDeclGenericTypeParam("source.lang.swift.decl.generic_type_param"); static UIdent KindRefGenericTypeParam("source.lang.swift.ref.generic_type_param"); static UIdent KindRefModule("source.lang.swift.ref.module"); static UIdent KindStmtForEach("source.lang.swift.stmt.foreach"); static UIdent KindStmtFor("source.lang.swift.stmt.for"); static UIdent KindStmtWhile("source.lang.swift.stmt.while"); static UIdent KindStmtRepeatWhile("source.lang.swift.stmt.repeatwhile"); static UIdent KindStmtIf("source.lang.swift.stmt.if"); static UIdent KindStmtGuard("source.lang.swift.stmt.guard"); static UIdent KindStmtSwitch("source.lang.swift.stmt.switch"); static UIdent KindStmtCase("source.lang.swift.stmt.case"); static UIdent KindStmtBrace("source.lang.swift.stmt.brace"); static UIdent KindExprCall("source.lang.swift.expr.call"); static UIdent KindExprArray("source.lang.swift.expr.array"); static UIdent KindExprDictionary("source.lang.swift.expr.dictionary"); static UIdent KindExprObjectLiteral("source.lang.swift.expr.object_literal"); static UIdent KindStructureElemId("source.lang.swift.structure.elem.id"); static UIdent KindStructureElemExpr("source.lang.swift.structure.elem.expr"); static UIdent KindStructureElemInitExpr("source.lang.swift.structure.elem.init_expr"); static UIdent KindStructureElemCondExpr("source.lang.swift.structure.elem.condition_expr"); static UIdent KindStructureElemPattern("source.lang.swift.structure.elem.pattern"); static UIdent KindStructureElemTypeRef("source.lang.swift.structure.elem.typeref"); std::unique_ptr LangSupport::createSwiftLangSupport(SourceKit::Context &SKCtx) { return std::unique_ptr(new SwiftLangSupport(SKCtx)); } const std::string LangSupport::SynthesizedUSRSeparator = "::SYNTHESIZED::"; namespace { class UIdentVisitor : public ASTVisitor { bool IsRef; public: explicit UIdentVisitor(bool IsRef) : IsRef(IsRef) { } /// TODO: reconsider whether having a default case is a good idea. UIdent visitDecl(const Decl *D) { return UIdent(); } UIdent visitFuncDecl(const FuncDecl *D); UIdent visitVarDecl(const VarDecl *D); UIdent visitParamDecl(const ParamDecl *D); UIdent visitExtensionDecl(const ExtensionDecl *D); UIdent visitAssociatedTypeDecl(const AssociatedTypeDecl *D) { return IsRef ? KindRefAssociatedType : KindDeclAssociatedType; } #define UID_FOR(CLASS) \ UIdent visit##CLASS##Decl(const CLASS##Decl *) { \ return IsRef ? KindRef##CLASS : KindDecl##CLASS; \ } UID_FOR(Class) UID_FOR(Struct) UID_FOR(Enum) UID_FOR(EnumElement) UID_FOR(Protocol) UID_FOR(TypeAlias) UID_FOR(GenericTypeParam) UID_FOR(Constructor) UID_FOR(Destructor) UID_FOR(Subscript) #undef UID_FOR }; } // anonymous namespace UIdent UIdentVisitor::visitFuncDecl(const FuncDecl *D) { if (D->isAccessor()) { return SwiftLangSupport::getUIDForAccessor(D->getAccessorStorageDecl(), D->getAccessorKind(), IsRef); } if (D->isOperator()) { switch (D->getOperatorDecl()->getKind()) { case DeclKind::PrefixOperator: return IsRef ? KindRefFunctionPrefixOperator : KindDeclFunctionPrefixOperator; case DeclKind::PostfixOperator: return IsRef ? KindRefFunctionPostfixOperator : KindDeclFunctionPostfixOperator; case DeclKind::InfixOperator: return IsRef ? KindRefFunctionInfixOperator : KindDeclFunctionInfixOperator; default: llvm_unreachable("unexpected operator kind"); } } const DeclContext *DC = D->getDeclContext(); if (DC->isTypeContext()) { if (D->isStatic()) { if (D->getCorrectStaticSpelling() == StaticSpellingKind::KeywordClass) return IsRef ? KindRefMethodClass : KindDeclMethodClass; else return IsRef ? KindRefMethodStatic : KindDeclMethodStatic; } return IsRef ? KindRefMethodInstance : KindDeclMethodInstance; } return IsRef ? KindRefFunctionFree : KindDeclFunctionFree; } UIdent UIdentVisitor::visitVarDecl(const VarDecl *D) { const DeclContext *DC = D->getDeclContext(); if (DC->isTypeContext()) { if (D->isStatic()) { if (D->getCorrectStaticSpelling() == StaticSpellingKind::KeywordClass) return IsRef ? KindRefVarClass : KindDeclVarClass; else return IsRef ? KindRefVarStatic : KindDeclVarStatic; } return IsRef ? KindRefVarInstance : KindDeclVarInstance; } if (DC->isLocalContext()) return IsRef ? KindRefVarLocal : KindDeclVarLocal; return IsRef ? KindRefVarGlobal : KindDeclVarGlobal; } UIdent UIdentVisitor::visitParamDecl(const ParamDecl *D) { // There is no KindRefVarParam. It's not usually an interesting difference. return IsRef ? KindRefVarLocal : KindDeclVarParam; } UIdent UIdentVisitor::visitExtensionDecl(const ExtensionDecl *D) { assert(!IsRef && "reference to an extension ?"); if (NominalTypeDecl *NTD = D->getExtendedType()->getAnyNominal()) { if (isa(NTD)) return KindDeclExtensionStruct; if (isa(NTD)) return KindDeclExtensionClass; if (isa(NTD)) return KindDeclExtensionEnum; if (isa(NTD)) return KindDeclExtensionProtocol; } return UIdent(); } SwiftLangSupport::SwiftLangSupport(SourceKit::Context &SKCtx) : SKCtx(SKCtx), CCCache(new SwiftCompletionCache) { llvm::SmallString<128> LibPath(SKCtx.getRuntimeLibPath()); llvm::sys::path::append(LibPath, "swift"); RuntimeResourcePath = LibPath.str(); ASTMgr.reset(new SwiftASTManager(*this)); // By default, just use the in-memory cache. CCCache->inMemory = llvm::make_unique(); } SwiftLangSupport::~SwiftLangSupport() { } UIdent SwiftLangSupport::getUIDForDecl(const Decl *D, bool IsRef) { return UIdentVisitor(IsRef).visit(const_cast(D)); } UIdent SwiftLangSupport::getUIDForLocalVar(bool IsRef) { return IsRef ? KindRefVarLocal : KindDeclVarLocal; } UIdent SwiftLangSupport::getUIDForAccessor(const ValueDecl *D, AccessorKind AccKind, bool IsRef) { switch (AccKind) { case AccessorKind::NotAccessor: llvm_unreachable("expected accessor"); case AccessorKind::IsMaterializeForSet: llvm_unreachable("unexpected MaterializeForSet"); case AccessorKind::IsGetter: return IsRef ? KindRefAccessorGetter : KindDeclAccessorGetter; case AccessorKind::IsSetter: return IsRef ? KindRefAccessorSetter : KindDeclAccessorSetter; case AccessorKind::IsWillSet: return IsRef ? KindRefAccessorWillSet : KindDeclAccessorWillSet; case AccessorKind::IsDidSet: return IsRef ? KindRefAccessorDidSet : KindDeclAccessorDidSet; case AccessorKind::IsAddressor: return IsRef ? KindRefAccessorAddress : KindDeclAccessorAddress; case AccessorKind::IsMutableAddressor: return IsRef ? KindRefAccessorMutableAddress : KindDeclAccessorMutableAddress; } } SourceKit::UIdent SwiftLangSupport::getUIDForModuleRef() { return KindRefModule; } UIdent SwiftLangSupport::getUIDForCodeCompletionDeclKind( ide::CodeCompletionDeclKind Kind, bool IsRef) { if (IsRef) { // FIXME: The code-completion kind is also used for semantic annotations. // We should either create a new kind or rename the code-completion kind to // something more general. switch (Kind) { case CodeCompletionDeclKind::Module: return KindRefModule; case CodeCompletionDeclKind::Class: return KindRefClass; case CodeCompletionDeclKind::Struct: return KindRefStruct; case CodeCompletionDeclKind::Enum: return KindRefEnum; case CodeCompletionDeclKind::EnumElement: return KindRefEnumElement; case CodeCompletionDeclKind::Protocol: return KindRefProtocol; case CodeCompletionDeclKind::AssociatedType: return KindRefAssociatedType; case CodeCompletionDeclKind::TypeAlias: return KindRefTypeAlias; case CodeCompletionDeclKind::GenericTypeParam: return KindRefGenericTypeParam; case CodeCompletionDeclKind::Constructor: return KindRefConstructor; case CodeCompletionDeclKind::Destructor: return KindRefDestructor; case CodeCompletionDeclKind::Subscript: return KindRefSubscript; case CodeCompletionDeclKind::StaticMethod: return KindRefMethodClass; case CodeCompletionDeclKind::InstanceMethod: return KindRefMethodInstance; case CodeCompletionDeclKind::PrefixOperatorFunction: return KindRefFunctionPrefixOperator; case CodeCompletionDeclKind::PostfixOperatorFunction: return KindRefFunctionPostfixOperator; case CodeCompletionDeclKind::InfixOperatorFunction: return KindRefFunctionInfixOperator; case CodeCompletionDeclKind::FreeFunction: return KindRefFunctionFree; case CodeCompletionDeclKind::StaticVar: return KindRefVarClass; case CodeCompletionDeclKind::InstanceVar: return KindRefVarInstance; case CodeCompletionDeclKind::LocalVar: return KindRefVarLocal; case CodeCompletionDeclKind::GlobalVar: return KindRefVarGlobal; } } switch (Kind) { case CodeCompletionDeclKind::Module: return KindDeclModule; case CodeCompletionDeclKind::Class: return KindDeclClass; case CodeCompletionDeclKind::Struct: return KindDeclStruct; case CodeCompletionDeclKind::Enum: return KindDeclEnum; case CodeCompletionDeclKind::EnumElement: return KindDeclEnumElement; case CodeCompletionDeclKind::Protocol: return KindDeclProtocol; case CodeCompletionDeclKind::AssociatedType: return KindDeclAssociatedType; case CodeCompletionDeclKind::TypeAlias: return KindDeclTypeAlias; case CodeCompletionDeclKind::GenericTypeParam: return KindDeclGenericTypeParam; case CodeCompletionDeclKind::Constructor: return KindDeclConstructor; case CodeCompletionDeclKind::Destructor: return KindDeclDestructor; case CodeCompletionDeclKind::Subscript: return KindDeclSubscript; case CodeCompletionDeclKind::StaticMethod: return KindDeclMethodClass; case CodeCompletionDeclKind::InstanceMethod: return KindDeclMethodInstance; case CodeCompletionDeclKind::PrefixOperatorFunction: return KindDeclFunctionPrefixOperator; case CodeCompletionDeclKind::PostfixOperatorFunction: return KindDeclFunctionPostfixOperator; case CodeCompletionDeclKind::InfixOperatorFunction: return KindDeclFunctionInfixOperator; case CodeCompletionDeclKind::FreeFunction: return KindDeclFunctionFree; case CodeCompletionDeclKind::StaticVar: return KindDeclVarClass; case CodeCompletionDeclKind::InstanceVar: return KindDeclVarInstance; case CodeCompletionDeclKind::LocalVar: return KindDeclVarLocal; case CodeCompletionDeclKind::GlobalVar: return KindDeclVarGlobal; } } UIdent SwiftLangSupport::getUIDForSyntaxNodeKind(SyntaxNodeKind SC) { static UIdent KindKeyword("source.lang.swift.syntaxtype.keyword"); static UIdent KindIdentifier("source.lang.swift.syntaxtype.identifier"); static UIdent KindTypeIdentifier("source.lang.swift.syntaxtype.typeidentifier"); static UIdent KindBuildConfigKeyword("source.lang.swift.syntaxtype.buildconfig.keyword"); static UIdent KindBuildConfigId("source.lang.swift.syntaxtype.buildconfig.id"); static UIdent KindAttributeId("source.lang.swift.syntaxtype.attribute.id"); static UIdent KindAttributeBuiltin("source.lang.swift.syntaxtype.attribute.builtin"); static UIdent KindNumber("source.lang.swift.syntaxtype.number"); static UIdent KindString("source.lang.swift.syntaxtype.string"); static UIdent KindStringInterpolation("source.lang.swift.syntaxtype.string_interpolation_anchor"); static UIdent KindComment("source.lang.swift.syntaxtype.comment"); static UIdent KindDocComment("source.lang.swift.syntaxtype.doccomment"); static UIdent KindDocCommentField("source.lang.swift.syntaxtype.doccomment.field"); static UIdent KindCommentMarker("source.lang.swift.syntaxtype.comment.mark"); static UIdent KindCommentURL("source.lang.swift.syntaxtype.comment.url"); static UIdent KindPlaceholder("source.lang.swift.syntaxtype.placeholder"); static UIdent KindObjectLiteral("source.lang.swift.syntaxtype.objectliteral"); switch (SC) { case SyntaxNodeKind::Keyword: return KindKeyword; case SyntaxNodeKind::Identifier: case SyntaxNodeKind::DollarIdent: return KindIdentifier; case SyntaxNodeKind::Integer: case SyntaxNodeKind::Floating: return KindNumber; case SyntaxNodeKind::String: return KindString; case SyntaxNodeKind::StringInterpolationAnchor: return KindStringInterpolation; case SyntaxNodeKind::CommentLine: case SyntaxNodeKind::CommentBlock: return KindComment; case SyntaxNodeKind::CommentMarker: return KindCommentMarker; case SyntaxNodeKind::CommentURL: return KindCommentURL; case SyntaxNodeKind::DocCommentLine: case SyntaxNodeKind::DocCommentBlock: return KindDocComment; case SyntaxNodeKind::DocCommentField: return KindDocCommentField; case SyntaxNodeKind::TypeId: return KindTypeIdentifier; case SyntaxNodeKind::BuildConfigKeyword: return KindBuildConfigKeyword; case SyntaxNodeKind::BuildConfigId: return KindBuildConfigId; case SyntaxNodeKind::AttributeId: return KindAttributeId; case SyntaxNodeKind::AttributeBuiltin: return KindAttributeBuiltin; case SyntaxNodeKind::EditorPlaceholder: return KindPlaceholder; case SyntaxNodeKind::ObjectLiteral: return KindObjectLiteral; } } UIdent SwiftLangSupport::getUIDForSyntaxStructureKind( SyntaxStructureKind Kind) { switch (Kind) { case SyntaxStructureKind::Class: return KindDeclClass; case SyntaxStructureKind::Struct: return KindDeclStruct; case SyntaxStructureKind::Protocol: return KindDeclProtocol; case SyntaxStructureKind::Enum: return KindDeclEnum; case SyntaxStructureKind::Extension: return KindDeclExtension; case SyntaxStructureKind::FreeFunction: return KindDeclFunctionFree; case SyntaxStructureKind::InstanceFunction: return KindDeclMethodInstance; case SyntaxStructureKind::StaticFunction: return KindDeclMethodStatic; case SyntaxStructureKind::ClassFunction: return KindDeclMethodClass; case SyntaxStructureKind::GlobalVariable: return KindDeclVarGlobal; case SyntaxStructureKind::InstanceVariable: return KindDeclVarInstance; case SyntaxStructureKind::StaticVariable: return KindDeclVarStatic; case SyntaxStructureKind::ClassVariable: return KindDeclVarClass; case SyntaxStructureKind::EnumCase: return KindDeclEnumCase; case SyntaxStructureKind::EnumElement: return KindDeclEnumElement; case SyntaxStructureKind::Parameter: return KindDeclVarParam; case SyntaxStructureKind::ForEachStatement: return KindStmtForEach; case SyntaxStructureKind::ForStatement: return KindStmtFor; case SyntaxStructureKind::WhileStatement: return KindStmtWhile; case SyntaxStructureKind::RepeatWhileStatement: return KindStmtRepeatWhile; case SyntaxStructureKind::IfStatement: return KindStmtIf; case SyntaxStructureKind::GuardStatement: return KindStmtGuard; case SyntaxStructureKind::SwitchStatement: return KindStmtSwitch; case SyntaxStructureKind::CaseStatement: return KindStmtCase; case SyntaxStructureKind::BraceStatement: return KindStmtBrace; case SyntaxStructureKind::CallExpression: return KindExprCall; case SyntaxStructureKind::ArrayExpression: return KindExprArray; case SyntaxStructureKind::DictionaryExpression: return KindExprDictionary; case SyntaxStructureKind::ObjectLiteralExpression: return KindExprObjectLiteral; } } UIdent SwiftLangSupport::getUIDForSyntaxStructureElementKind( SyntaxStructureElementKind Kind) { switch (Kind) { case SyntaxStructureElementKind::Id: return KindStructureElemId; case SyntaxStructureElementKind::Expr: return KindStructureElemExpr; case SyntaxStructureElementKind::InitExpr: return KindStructureElemInitExpr; case SyntaxStructureElementKind::ConditionExpr: return KindStructureElemCondExpr; case SyntaxStructureElementKind::Pattern: return KindStructureElemPattern; case SyntaxStructureElementKind::TypeRef: return KindStructureElemTypeRef; } } bool SwiftLangSupport::printDisplayName(const swift::ValueDecl *D, llvm::raw_ostream &OS) { if (!D->hasName()) return true; OS << D->getFullName(); return false; } bool SwiftLangSupport::printUSR(const ValueDecl *D, llvm::raw_ostream &OS) { return ide::printDeclUSR(D, OS); } bool SwiftLangSupport::printAccessorUSR(const AbstractStorageDecl *D, AccessorKind AccKind, llvm::raw_ostream &OS) { return ide::printAccessorUSR(D, AccKind, OS); } std::string SwiftLangSupport::resolvePathSymlinks(StringRef FilePath) { std::string InputPath = FilePath; char full_path[MAXPATHLEN]; if (const char *path = realpath(InputPath.c_str(), full_path)) return path; return InputPath; } CloseClangModuleFiles::~CloseClangModuleFiles() { clang::Preprocessor &PP = loader.getClangPreprocessor(); clang::ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap(); for (auto I = ModMap.module_begin(), E = ModMap.module_end(); I != E; ++I) { clang::Module *M = I->second; if (!M->isSubModule() && M->getASTFile()) M->getASTFile()->closeFile(); } }