void handlePrimaryAST(ASTUnitRef AstUnit) override { auto &CompIns = AstUnit->getCompilerInstance(); Module *MainModule = CompIns.getMainModule(); unsigned BufferID = AstUnit->getPrimarySourceFile().getBufferID().getValue(); SourceLoc Loc = Lexer::getLocForStartOfToken(CompIns.getSourceMgr(), BufferID, Offset); if (Loc.isInvalid()) { Receiver({}); return; } trace::TracedOperation TracedOp; if (trace::enabled()) { trace::SwiftInvocation SwiftArgs; ASTInvok->raw(SwiftArgs.Args.Args, SwiftArgs.Args.PrimaryFile); trace::initTraceFiles(SwiftArgs, CompIns); TracedOp.start(trace::OperationKind::CursorInfoForSource, SwiftArgs, {std::make_pair("Offset", std::to_string(Offset))}); } SemaLocResolver Resolver(AstUnit->getPrimarySourceFile()); SemaToken SemaTok = Resolver.resolve(Loc); if (SemaTok.isInvalid()) { Receiver({}); return; } CompilerInvocation CompInvok; ASTInvok->applyTo(CompInvok); if (SemaTok.Mod) { passCursorInfoForModule(SemaTok.Mod, Lang.getIFaceGenContexts(), CompInvok, Receiver); } else { ValueDecl *VD = SemaTok.CtorTyRef ? SemaTok.CtorTyRef : SemaTok.ValueD; bool Failed = passCursorInfoForDecl(VD, MainModule, SemaTok.Ty, SemaTok.IsRef, BufferID, Lang, CompInvok, PreviousASTSnaps, Receiver); if (Failed) { if (!PreviousASTSnaps.empty()) { // Attempt again using the up-to-date AST. resolveCursor(Lang, InputFile, Offset, ASTInvok, /*TryExistingAST=*/false, Receiver); } else { Receiver({}); } } } }
/// Returns true for failure to resolve. static bool passCursorInfoForDecl(const ValueDecl *VD, const Module *MainModule, const Type Ty, bool IsRef, Optional<unsigned> OrigBufferID, SwiftLangSupport &Lang, const CompilerInvocation &Invok, ArrayRef<ImmutableTextSnapshotRef> PreviousASTSnaps, std::function<void(const CursorInfo &)> Receiver) { if (AvailableAttr::isUnavailable(VD)) return true; SmallString<64> SS; auto BaseType = findBaseTypeForReplacingArchetype(VD, Ty); unsigned NameBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); SwiftLangSupport::printDisplayName(VD, OS); } unsigned NameEnd = SS.size(); unsigned USRBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); SwiftLangSupport::printUSR(VD, OS); } unsigned USREnd = SS.size(); unsigned TypenameBegin = SS.size(); if (VD->hasType()) { llvm::raw_svector_ostream OS(SS); VD->getType().print(OS); } unsigned TypenameEnd = SS.size(); unsigned DocCommentBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); ide::getDocumentationCommentAsXML(VD, OS); } unsigned DocCommentEnd = SS.size(); unsigned DeclBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); printAnnotatedDeclaration(VD, Ty, BaseType, OS); } unsigned DeclEnd = SS.size(); SmallVector<std::pair<unsigned, unsigned>, 4> OverUSROffs; ide::walkOverriddenDecls(VD, [&](llvm::PointerUnion<const ValueDecl*, const clang::NamedDecl*> D) { unsigned OverUSRBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); if (auto VD = D.dyn_cast<const ValueDecl*>()) { if (SwiftLangSupport::printUSR(VD, OS)) return; } else { llvm::SmallString<128> Buf; if (clang::index::generateUSRForDecl( D.get<const clang::NamedDecl*>(), Buf)) return; OS << Buf.str(); } } unsigned OverUSREnd = SS.size(); OverUSROffs.push_back(std::make_pair(OverUSRBegin, OverUSREnd)); }); SmallVector<std::pair<unsigned, unsigned>, 4> RelDeclOffs; walkRelatedDecls(VD, [&](const ValueDecl *RelatedDecl, bool DuplicateName) { unsigned RelatedDeclBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); OS<<"<RelatedName usr=\""; SwiftLangSupport::printUSR(RelatedDecl, OS); OS<<"\">"; if (isa<AbstractFunctionDecl>(RelatedDecl) && DuplicateName) { // Related decls are generally overloads, so print parameter types to // differentiate them. PrintOptions PO; PO.SkipAttributes = true; PO.SkipIntroducerKeywords = true; PO.ArgAndParamPrinting = PrintOptions::ArgAndParamPrintingMode::ArgumentOnly; XMLEscapingPrinter Printer(OS); if (BaseType) PO.setArchetypeTransform(BaseType, VD->getDeclContext()); RelatedDecl->print(Printer, PO); } else { llvm::SmallString<128> Buf; { llvm::raw_svector_ostream OSBuf(Buf); SwiftLangSupport::printDisplayName(RelatedDecl, OSBuf); } llvm::markup::appendWithXMLEscaping(OS, Buf); } OS<<"</RelatedName>"; } unsigned RelatedDeclEnd = SS.size(); RelDeclOffs.push_back(std::make_pair(RelatedDeclBegin, RelatedDeclEnd)); }); ASTContext &Ctx = VD->getASTContext(); ClangImporter *Importer = static_cast<ClangImporter*>( Ctx.getClangModuleLoader()); std::string ModuleName; auto ClangNode = VD->getClangNode(); if (ClangNode) { auto ClangMod = Importer->getClangOwningModule(ClangNode); ModuleName = ClangMod->getFullModuleName(); } else if (VD->getLoc().isInvalid() && VD->getModuleContext() != MainModule) { ModuleName = VD->getModuleContext()->getName().str(); } StringRef ModuleInterfaceName; if (auto IFaceGenRef = Lang.getIFaceGenContexts().find(ModuleName, Invok)) ModuleInterfaceName = IFaceGenRef->getDocumentName(); UIdent Kind = SwiftLangSupport::getUIDForDecl(VD, IsRef); StringRef Name = StringRef(SS.begin()+NameBegin, NameEnd-NameBegin); StringRef USR = StringRef(SS.begin()+USRBegin, USREnd-USRBegin); StringRef TypeName = StringRef(SS.begin()+TypenameBegin, TypenameEnd-TypenameBegin); StringRef DocComment = StringRef(SS.begin()+DocCommentBegin, DocCommentEnd-DocCommentBegin); StringRef AnnotatedDecl = StringRef(SS.begin()+DeclBegin, DeclEnd-DeclBegin); llvm::Optional<std::pair<unsigned, unsigned>> DeclarationLoc; StringRef Filename; getLocationInfo(VD, DeclarationLoc, Filename); if (DeclarationLoc.hasValue()) { DeclarationLoc = tryRemappingLocToLatestSnapshot(Lang, *DeclarationLoc, Filename, PreviousASTSnaps); if (!DeclarationLoc.hasValue()) return true; // failed to remap. } SmallVector<StringRef, 4> OverUSRs; for (auto Offs : OverUSROffs) { OverUSRs.push_back(StringRef(SS.begin()+Offs.first, Offs.second-Offs.first)); } SmallVector<StringRef, 4> AnnotatedRelatedDecls; for (auto Offs : RelDeclOffs) { AnnotatedRelatedDecls.push_back(StringRef(SS.begin() + Offs.first, Offs.second - Offs.first)); } bool IsSystem = VD->getModuleContext()->isSystemModule(); std::string TypeInterface; CursorInfo Info; Info.Kind = Kind; Info.Name = Name; Info.USR = USR; Info.TypeName = TypeName; Info.DocComment = DocComment; Info.AnnotatedDeclaration = AnnotatedDecl; Info.ModuleName = ModuleName; Info.ModuleInterfaceName = ModuleInterfaceName; Info.DeclarationLoc = DeclarationLoc; Info.Filename = Filename; Info.OverrideUSRs = OverUSRs; Info.AnnotatedRelatedDeclarations = AnnotatedRelatedDecls; Info.IsSystem = IsSystem; Info.TypeInterface = ASTPrinter::printTypeInterface(Ty, VD->getDeclContext(), TypeInterface) ? StringRef(TypeInterface) : StringRef(); Receiver(Info); return false; }