static void indexModule(llvm::MemoryBuffer *Input, StringRef ModuleName, StringRef Hash, IndexingConsumer &IdxConsumer, CompilerInstance &CI, ArrayRef<const char *> Args) { trace::TracedOperation TracedOp; if (trace::enabled()) { trace::SwiftInvocation SwiftArgs; SwiftArgs.Args.Args.assign(Args.begin(), Args.end()); SwiftArgs.Args.PrimaryFile = Input->getBufferIdentifier(); SwiftArgs.addFile(Input->getBufferIdentifier(), Input->getBuffer()); trace::StringPairs OpArgs; OpArgs.push_back(std::make_pair("ModuleName", ModuleName)); OpArgs.push_back(std::make_pair("Hash", Hash)); TracedOp.start(trace::OperationKind::IndexModule, SwiftArgs, OpArgs); } ASTContext &Ctx = CI.getASTContext(); std::unique_ptr<SerializedModuleLoader> Loader; Module *Mod = nullptr; if (ModuleName == Ctx.StdlibModuleName.str()) { Mod = Ctx.getModule({ {Ctx.StdlibModuleName, SourceLoc()} }); } else { Loader = SerializedModuleLoader::create(Ctx); auto Buf = std::unique_ptr<llvm::MemoryBuffer>( llvm::MemoryBuffer::getMemBuffer(Input->getBuffer(), Input->getBufferIdentifier())); // FIXME: These APIs allocate memory on the ASTContext, meaning it may not // be freed for a long time. Mod = Module::create(Ctx.getIdentifier(ModuleName), Ctx); // Indexing is not using documentation now, so don't open the module // documentation file. // FIXME: refactor the frontend to provide an easy way to figure out the // correct filename here. auto FUnit = Loader->loadAST(*Mod, None, std::move(Buf), nullptr); // FIXME: Not knowing what went wrong is pretty bad. loadModule() should be // more modular, rather than emitting diagnostics itself. if (!FUnit) { IdxConsumer.failed("failed to load module"); return; } } // Setup a typechecker for protocol conformance resolving. OwnedResolver TypeResolver = createLazyResolver(Ctx); IndexSwiftASTWalker Walker(IdxConsumer, Ctx, /*BufferID=*/-1); Walker.visitModule(*Mod, Hash); }
static void indexModule(llvm::MemoryBuffer *Input, StringRef ModuleName, StringRef Hash, IndexingConsumer &IdxConsumer, CompilerInstance &CI, ArrayRef<const char *> Args) { ASTContext &Ctx = CI.getASTContext(); std::unique_ptr<SerializedModuleLoader> Loader; ModuleDecl *Mod = nullptr; if (ModuleName == Ctx.StdlibModuleName.str()) { Mod = Ctx.getModule({ {Ctx.StdlibModuleName, SourceLoc()} }); } else { Loader = SerializedModuleLoader::create(Ctx); auto Buf = std::unique_ptr<llvm::MemoryBuffer>( llvm::MemoryBuffer::getMemBuffer(Input->getBuffer(), Input->getBufferIdentifier())); // FIXME: These APIs allocate memory on the ASTContext, meaning it may not // be freed for a long time. Mod = ModuleDecl::create(Ctx.getIdentifier(ModuleName), Ctx); // Indexing is not using documentation now, so don't open the module // documentation file. // FIXME: refactor the frontend to provide an easy way to figure out the // correct filename here. auto FUnit = Loader->loadAST(*Mod, None, std::move(Buf), nullptr); // FIXME: Not knowing what went wrong is pretty bad. loadModule() should be // more modular, rather than emitting diagnostics itself. if (!FUnit) { IdxConsumer.failed("failed to load module"); return; } Mod->setHasResolvedImports(); } // Setup a typechecker for protocol conformance resolving. (void)createTypeChecker(Ctx); SKIndexDataConsumer IdxDataConsumer(IdxConsumer); index::indexModule(Mod, Hash, IdxDataConsumer); }
void SwiftLangSupport::indexSource(StringRef InputFile, IndexingConsumer &IdxConsumer, ArrayRef<const char *> Args, StringRef Hash) { std::string Error; auto InputBuf = ASTMgr->getMemoryBuffer(InputFile, Error); if (!InputBuf) { IdxConsumer.failed(Error); return; } StringRef Filename = llvm::sys::path::filename(InputFile); StringRef FileExt = llvm::sys::path::extension(Filename); bool IsModuleIndexing = (FileExt == ".swiftmodule" || FileExt == ".pcm"); CompilerInstance CI; // Display diagnostics to stderr. PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); CompilerInvocation Invocation; bool Failed = getASTManager().initCompilerInvocation(Invocation, Args, CI.getDiags(), /*PrimaryFile=*/IsModuleIndexing ? StringRef() : InputFile, Error); if (Failed) { IdxConsumer.failed(Error); return; } if (IsModuleIndexing) { if (CI.setup(Invocation)) return; bool IsClangModule = (FileExt == ".pcm"); if (IsClangModule) { IdxConsumer.failed("Clang module files are not supported"); return; } indexModule(InputBuf.get(), llvm::sys::path::stem(Filename), Hash, IdxConsumer, CI, Args); return; } if (Invocation.getInputFilenames().empty()) { IdxConsumer.failed("no input filenames specified"); return; } if (CI.setup(Invocation)) return; trace::TracedOperation TracedOp; if (trace::enabled()) { trace::SwiftInvocation SwiftArgs; trace::initTraceInfo(SwiftArgs, InputFile, Args); trace::initTraceFiles(SwiftArgs, CI); TracedOp.start(trace::OperationKind::IndexSource, SwiftArgs); } CI.performSema(); // NOTE: performSema() may end up with some gruesome error preventing it from // setting primary file correctly if (!CI.getPrimarySourceFile()) { IdxConsumer.failed("no primary source file found"); return; } // Setup a typechecker for protocol conformance resolving. OwnedResolver TypeResolver = createLazyResolver(CI.getASTContext()); unsigned BufferID = CI.getPrimarySourceFile()->getBufferID().getValue(); IndexSwiftASTWalker Walker(IdxConsumer, CI.getASTContext(), BufferID); Walker.visitModule(*CI.getMainModule(), Hash); }
void SwiftLangSupport::indexSource(StringRef InputFile, IndexingConsumer &IdxConsumer, ArrayRef<const char *> OrigArgs, StringRef Hash) { std::string Error; auto InputBuf = ASTMgr->getMemoryBuffer(InputFile, Error); if (!InputBuf) { IdxConsumer.failed(Error); return; } StringRef Filename = llvm::sys::path::filename(InputFile); StringRef FileExt = llvm::sys::path::extension(Filename); bool IsModuleIndexing = (FileExt == ".swiftmodule" || FileExt == ".pcm"); CompilerInstance CI; // Display diagnostics to stderr. PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); // Add -disable-typo-correction, since the errors won't be captured in the // response, and it can be expensive to do typo-correction when there are many // errors, which is common in indexing. SmallVector<const char *, 16> Args(OrigArgs.begin(), OrigArgs.end()); Args.push_back("-Xfrontend"); Args.push_back("-disable-typo-correction"); CompilerInvocation Invocation; bool Failed = true; if (IsModuleIndexing) { Failed = getASTManager()->initCompilerInvocationNoInputs( Invocation, Args, CI.getDiags(), Error); } else { Failed = getASTManager()->initCompilerInvocation( Invocation, Args, CI.getDiags(), InputFile, Error); } if (Failed) { IdxConsumer.failed(Error); return; } if (IsModuleIndexing) { if (CI.setup(Invocation)) return; bool IsClangModule = (FileExt == ".pcm"); if (IsClangModule) { IdxConsumer.failed("Clang module files are not supported"); return; } indexModule(InputBuf.get(), llvm::sys::path::stem(Filename), Hash, IdxConsumer, CI, Args); return; } if (!Invocation.getFrontendOptions().InputsAndOutputs.hasInputs()) { IdxConsumer.failed("no input filenames specified"); return; } if (CI.setup(Invocation)) return; trace::TracedOperation TracedOp(trace::OperationKind::IndexSource); if (TracedOp.enabled()) { trace::SwiftInvocation SwiftArgs; trace::initTraceInfo(SwiftArgs, InputFile, Args); TracedOp.start(SwiftArgs); } CI.performSema(); // NOTE: performSema() may end up with some gruesome error preventing it from // setting primary file correctly if (!CI.getPrimarySourceFile()) { IdxConsumer.failed("no primary source file found"); return; } // Setup a typechecker for protocol conformance resolving. (void)createTypeChecker(CI.getASTContext()); SKIndexDataConsumer IdxDataConsumer(IdxConsumer); index::indexSourceFile(CI.getPrimarySourceFile(), Hash, IdxDataConsumer); }