in tools/swift-ide-test/swift-ide-test.cpp [4120:4647]
int main(int argc, char *argv[]) {
PROGRAM_START(argc, argv);
INITIALIZE_LLVM();
if (argc > 1) {
// Handle integrated test tools which do not use
// llvm::cl::ParseCommandLineOptions.
StringRef FirstArg(argv[1]);
if (FirstArg == "-test-createCompilerInvocation") {
bool ForceNoOutputs = false;
ArrayRef<const char *> Args(argv + 2, argc - 2);
if (argc > 2 && StringRef(argv[2]) == "-force-no-outputs") {
ForceNoOutputs = true;
Args = Args.drop_front();
}
return doTestCreateCompilerInvocation(Args, ForceNoOutputs);
}
}
// '--cc-args' separates swift-ide-test options from clang arguments.
ArrayRef<const char *> CCArgs;
for (int i = 1; i < argc; ++i) {
if (StringRef(argv[i]) == "--cc-args") {
CCArgs = llvm::makeArrayRef(argv+i+1, argc-i-1);
argc = i;
}
}
llvm::cl::HideUnrelatedOptions(options::Category);
llvm::cl::ParseCommandLineOptions(argc, argv, "Swift IDE Test\n");
if (options::Action == ActionType::None) {
llvm::errs() << "action required\n";
llvm::cl::PrintHelpMessage();
return 1;
}
if (options::Action == ActionType::TestCreateCompilerInvocation) {
llvm::errs() << "-test-createCompilerInvocation must be specified before "
"all other arguments\n";
return 1;
}
if (options::Action == ActionType::GenerateModuleAPIDescription) {
return doGenerateModuleAPIDescription(
llvm::sys::fs::getMainExecutable(
argv[0], reinterpret_cast<void *>(&anchorForGetMainExecutable)),
options::InputFilenames);
}
if (options::Action == ActionType::DumpCompletionCache) {
if (options::InputFilenames.empty()) {
llvm::errs() << "-dump-completion-cache requires an input file\n";
return 1;
}
for (StringRef filename : options::InputFilenames) {
auto resultsOpt = ide::OnDiskCodeCompletionCache::getFromFile(filename);
if (!resultsOpt) {
// FIXME: error?
continue;
}
printCodeCompletionResultsImpl(
resultsOpt->get()->Sink.Results, llvm::outs(),
options::CodeCompletionKeywords, options::CodeCompletionComments,
options::CodeCompletionSourceText,
options::CodeCompletionAnnotateResults);
}
return 0;
}
if (options::SourceFilename.empty()) {
llvm::errs() << "source file required\n";
llvm::cl::PrintHelpMessage();
return 1;
}
if (options::Action == ActionType::CompilerInvocationFromModule) {
return doTestCompilerInvocationFromModule(options::SourceFilename);
}
// If no SDK was specified via -sdk, check environment variable SDKROOT.
if (options::SDK.getNumOccurrences() == 0) {
const char *SDKROOT = getenv("SDKROOT");
if (SDKROOT)
options::SDK = SDKROOT;
}
if (options::PrintStats)
llvm::EnableStatistics();
CompilerInvocation InitInvok;
InitInvok.getFrontendOptions().RequestedAction = FrontendOptions::ActionType::Typecheck;
for (auto &File : options::InputFilenames)
InitInvok.getFrontendOptions().InputsAndOutputs.addInputFile(File);
InitInvok.setMainExecutablePath(
llvm::sys::fs::getMainExecutable(argv[0],
reinterpret_cast<void *>(&anchorForGetMainExecutable)));
InitInvok.setModuleName(options::ModuleName);
InitInvok.setSDKPath(options::SDK);
if (!options::DefineAvailability.empty()) {
InitInvok.getLangOptions().AvailabilityMacros.push_back(options::DefineAvailability);
}
for (auto map: options::SerializedPathObfuscate) {
auto SplitMap = StringRef(map).split('=');
InitInvok.getFrontendOptions().serializedPathObfuscator
.addMapping(SplitMap.first, SplitMap.second);
InitInvok.getSearchPathOptions().DeserializedPathRecoverer
.addMapping(SplitMap.first, SplitMap.second);
}
InitInvok.getLangOptions().CollectParsedToken = true;
InitInvok.getLangOptions().BuildSyntaxTree = true;
InitInvok.getLangOptions().EnableCrossImportOverlays =
options::EnableCrossImportOverlays;
if (options::DisableObjCInterop) {
InitInvok.getLangOptions().EnableObjCInterop = false;
} else if (options::EnableObjCInterop) {
InitInvok.getLangOptions().EnableObjCInterop = true;
} else if (!options::Triple.empty()) {
InitInvok.getLangOptions().EnableObjCInterop =
llvm::Triple(options::Triple).isOSDarwin();
}
if (options::EnableCxxInterop) {
InitInvok.getLangOptions().EnableCXXInterop = true;
}
if (options::EnableExperimentalConcurrency) {
InitInvok.getLangOptions().EnableExperimentalConcurrency = true;
}
if (options::WarnConcurrency) {
InitInvok.getLangOptions().WarnConcurrency = true;
}
if (options::DisableImplicitConcurrencyImport) {
InitInvok.getLangOptions().DisableImplicitConcurrencyModuleImport = true;
}
if (options::EnableExperimentalNamedOpaqueTypes) {
InitInvok.getLangOptions().EnableExperimentalNamedOpaqueTypes = true;
}
if (options::EnableExperimentalDistributed) {
// distributed implies concurrency features:
InitInvok.getLangOptions().EnableExperimentalConcurrency = true;
// enable 'distributed' parsing and features
InitInvok.getLangOptions().EnableExperimentalDistributed = true;
}
if (!options::Triple.empty())
InitInvok.setTargetTriple(options::Triple);
if (!options::SwiftVersion.empty()) {
// Honor the *last* -swift-version specified.
const auto &LastSwiftVersion =
options::SwiftVersion[options::SwiftVersion.size()-1];
if (auto swiftVersion =
version::Version::parseVersionString(LastSwiftVersion,
SourceLoc(), nullptr)) {
if (auto actual = swiftVersion.getValue().getEffectiveLanguageVersion())
InitInvok.getLangOptions().EffectiveLanguageVersion = actual.getValue();
}
}
if (!options::ToolsDirectory.empty()) {
SmallString<128> toolsDir(options::ToolsDirectory);
llvm::sys::path::append(toolsDir, "clang");
InitInvok.getClangImporterOptions().clangPath =
std::string(toolsDir);
}
if (!options::ModuleCachePath.empty()) {
// Honor the *last* -module-cache-path specified.
InitInvok.getClangImporterOptions().ModuleCachePath =
options::ModuleCachePath[options::ModuleCachePath.size()-1];
}
if (!options::AccessNotesPath.empty()) {
InitInvok.getFrontendOptions().AccessNotesPath =
options::AccessNotesPath[options::AccessNotesPath.size()-1];
}
if (options::ParseAsLibrary) {
InitInvok.getFrontendOptions().InputMode =
swift::FrontendOptions::ParseInputMode::SwiftLibrary;
}
InitInvok.getClangImporterOptions().PrecompiledHeaderOutputDir =
options::PCHOutputDir;
InitInvok.setImportSearchPaths(options::ImportPaths);
std::vector<SearchPathOptions::FrameworkSearchPath> FramePaths;
for (const auto &path : options::FrameworkPaths) {
FramePaths.push_back({path, /*isSystem=*/false});
}
for (const auto &path : options::SystemFrameworkPaths) {
FramePaths.push_back({path, /*isSystem=*/true});
}
InitInvok.setFrameworkSearchPaths(FramePaths);
InitInvok.getFrontendOptions().EnableSourceImport |=
options::EnableSourceImport;
InitInvok.getFrontendOptions().ImplicitObjCHeaderPath =
options::ImportObjCHeader;
InitInvok.getClangImporterOptions().BridgingHeader =
options::ImportObjCHeader;
InitInvok.getLangOptions().EnableAccessControl =
!options::DisableAccessControl;
InitInvok.getLangOptions().EnableSwift3ObjCInference =
options::EnableSwift3ObjCInference;
InitInvok.getClangImporterOptions().ImportForwardDeclarations |=
options::ObjCForwardDeclarations;
if (!options::ResourceDir.empty()) {
InitInvok.setRuntimeResourcePath(options::ResourceDir);
}
for (auto &Arg : options::ClangXCC) {
InitInvok.getClangImporterOptions().ExtraArgs.push_back(Arg);
}
InitInvok.getLangOptions().EnableObjCAttrRequiresFoundation =
!options::DisableObjCAttrRequiresFoundationModule;
InitInvok.getTypeCheckerOptions().DebugForbidTypecheckPrefix =
options::DebugForbidTypecheckPrefix;
InitInvok.getTypeCheckerOptions().DebugConstraintSolver =
options::DebugConstraintSolver;
for (auto ConfigName : options::BuildConfigs)
InitInvok.getLangOptions().addCustomConditionalCompilationFlag(ConfigName);
if (!options::ExplicitSwiftModuleMap.empty()) {
InitInvok.getSearchPathOptions().ExplicitSwiftModuleMap =
options::ExplicitSwiftModuleMap;
InitInvok.getFrontendOptions().DisableImplicitModules = true;
}
if (options::AllowCompilerErrors) {
InitInvok.getFrontendOptions().AllowModuleWithCompilerErrors = true;
InitInvok.getLangOptions().AllowModuleWithCompilerErrors = true;
}
if (!options::ModuleAliases.empty()) {
PrintingDiagnosticConsumer PDC;
SourceManager SM;
DiagnosticEngine Diags(SM);
Diags.addConsumer(PDC);
if (!InitInvok.setModuleAliasMap(options::ModuleAliases, Diags)) {
llvm::errs() << "invalid module alias arguments\n";
return 1;
}
}
// Process the clang arguments last and allow them to override previously
// set options.
if (!CCArgs.empty()) {
std::string Error;
if (initInvocationByClangArguments(CCArgs, InitInvok, Error)) {
llvm::errs() << "error initializing invocation with clang args: "
<< Error << '\n';
return 1;
}
}
PrintOptions PrintOpts;
if (options::PrintInterface) {
PrintOpts = PrintOptions::printModuleInterface(
InitInvok.getFrontendOptions().PrintFullConvention);
} else if (options::PrintInterfaceForDoc) {
PrintOpts = PrintOptions::printDocInterface();
} else {
PrintOpts = PrintOptions::printEverything();
PrintOpts.FullyQualifiedTypes = options::FullyQualifiedTypes;
PrintOpts.FullyQualifiedTypesIfAmbiguous =
options::FullyQualifiedTypesIfAmbiguous;
PrintOpts.SynthesizeSugarOnTypes = options::SynthesizeSugarOnTypes;
PrintOpts.AbstractAccessors = options::AbstractAccessors;
PrintOpts.FunctionDefinitions = options::FunctionDefinitions;
PrintOpts.PrintExprs = options::Expressions;
PrintOpts.PreferTypeRepr = options::PreferTypeRepr;
PrintOpts.ExplodePatternBindingDecls = options::ExplodePatternBindingDecls;
PrintOpts.PrintImplicitAttrs = options::PrintImplicitAttrs;
PrintOpts.PrintAccess = options::PrintAccess;
PrintOpts.AccessFilter = options::AccessFilter;
PrintOpts.PrintDocumentationComments = !options::SkipDocumentationComments;
PrintOpts.PrintRegularClangComments = options::PrintRegularComments;
PrintOpts.SkipPrivateStdlibDecls = options::SkipPrivateStdlibDecls;
PrintOpts.SkipUnavailable = options::SkipUnavailable;
PrintOpts.SkipDeinit = options::SkipDeinit;
PrintOpts.SkipImports = options::SkipImports;
PrintOpts.SkipOverrides = options::SkipOverrides;
if (options::SkipParameterNames) {
PrintOpts.ArgAndParamPrinting
= PrintOptions::ArgAndParamPrintingMode::ArgumentOnly;
} else if (options::AlwaysArgumentLabels) {
PrintOpts.ArgAndParamPrinting
= PrintOptions::ArgAndParamPrintingMode::BothAlways;
}
}
if (options::SkipUnderscoredStdlibProtocols)
PrintOpts.SkipUnderscoredStdlibProtocols = true;
if (options::PrintOriginalSourceText)
PrintOpts.PrintOriginalSourceText = true;
if (PrintOpts.PrintDocumentationComments) {
InitInvok.getLangOptions().AttachCommentsToDecls = true;
}
int ExitCode;
switch (options::Action) {
case ActionType::None:
case ActionType::TestCreateCompilerInvocation:
case ActionType::CompilerInvocationFromModule:
case ActionType::GenerateModuleAPIDescription:
case ActionType::DiffModuleAPI:
case ActionType::DumpCompletionCache:
llvm_unreachable("should be handled above");
case ActionType::BatchCodeCompletion:
if (options::FileCheckPath.empty() && !options::SkipFileCheck) {
llvm::errs() << "'FileCheck' path required or explicitly specify "
<< "'-skip-filecheck'\n";
return 1;
}
ExitCode = doBatchCodeCompletion(
InitInvok, options::SourceFilename, options::CodeCompletionDiagnostics,
options::CodeCompletionKeywords, options::CodeCompletionComments,
options::CodeCompletionAnnotateResults,
options::CodeCompleteInitsInPostfixExpr,
options::CodeCompleteCallPatternHeuristics,
options::CodeCompletionAddCallWithNoDefaultArgs,
options::CodeCompletionSourceText);
break;
case ActionType::CodeCompletion:
if (options::CodeCompletionToken.empty()) {
llvm::errs() << "code completion token name required\n";
return 1;
}
ExitCode = doCodeCompletion(
InitInvok, options::SourceFilename, options::SecondSourceFilename,
options::CodeCompletionToken, options::CodeCompletionDiagnostics,
options::CodeCompletionKeywords, options::CodeCompletionComments,
options::CodeCompletionAnnotateResults,
options::CodeCompleteInitsInPostfixExpr,
options::CodeCompleteCallPatternHeuristics,
options::CodeCompletionAddCallWithNoDefaultArgs,
options::CodeCompletionSourceText);
break;
case ActionType::REPLCodeCompletion:
ExitCode = doREPLCodeCompletion(InitInvok, options::SourceFilename);
break;
case ActionType::TypeContextInfo:
if (options::CodeCompletionToken.empty()) {
llvm::errs() << "token name required\n";
return 1;
}
ExitCode = doTypeContextInfo(InitInvok,
options::SourceFilename,
options::SecondSourceFilename,
options::CodeCompletionToken,
options::CodeCompletionDiagnostics);
break;
case ActionType::PrintExpressionTypes:
ExitCode = doPrintExpressionTypes(InitInvok,
options::SourceFilename);
break;
case ActionType::ConformingMethodList:
if (options::CodeCompletionToken.empty()) {
llvm::errs() << "token name required\n";
return 1;
}
ExitCode = doConformingMethodList(InitInvok,
options::SourceFilename,
options::SecondSourceFilename,
options::CodeCompletionToken,
options::CodeCompletionDiagnostics,
options::ConformingMethodListExpectedTypes);
break;
case ActionType::SyntaxColoring:
ExitCode = doSyntaxColoring(InitInvok,
options::SourceFilename,
options::TerminalOutput,
options::Typecheck,
options::Playground);
break;
case ActionType::DumpImporterLookupTable:
ExitCode = doDumpImporterLookupTables(InitInvok, options::SourceFilename);
break;
case ActionType::Structure:
ExitCode = doStructureAnnotation(InitInvok, options::SourceFilename);
break;
case ActionType::Annotation:
ExitCode = doSemanticAnnotation(InitInvok,
options::SourceFilename,
options::TerminalOutput);
break;
case ActionType::TestInputCompleteness:
ExitCode = doInputCompletenessTest(options::SourceFilename);
break;
case ActionType::PrintASTNotTypeChecked:
case ActionType::PrintASTTypeChecked: {
bool RunTypeChecker = (options::Action == ActionType::PrintASTTypeChecked);
ExitCode = doPrintAST(InitInvok,
options::SourceFilename,
RunTypeChecker,
PrintOpts,
options::MangledNameToFind,
options::DebugClientDiscriminator);
break;
}
case ActionType::PrintLocalTypes:
ExitCode = doPrintLocalTypes(InitInvok, options::ModuleToPrint);
break;
case ActionType::PrintModuleGroups:
case ActionType::PrintModule: {
ide::ModuleTraversalOptions TraversalOptions;
if (options::ModulePrintSubmodules)
TraversalOptions |= ide::ModuleTraversal::VisitSubmodules;
if (options::ModulePrintHidden)
TraversalOptions |= ide::ModuleTraversal::VisitHidden;
if (options::ModulePrintSkipOverlay)
TraversalOptions |= ide::ModuleTraversal::SkipOverlay;
if (options::Action == ActionType::PrintModuleGroups)
ExitCode = doPrintModuleGroups(InitInvok, options::ModuleToPrint);
else {
if (options::NoEmptyLineBetweenMembers.getNumOccurrences() > 0)
PrintOpts.EmptyLineBetweenMembers = !options::NoEmptyLineBetweenMembers;
ExitCode = doPrintModules(
InitInvok, options::ModuleToPrint, options::ModuleGroupToPrint,
TraversalOptions, PrintOpts, options::AnnotatePrint,
options::SynthesizeExtension);
}
break;
}
case ActionType::PrintModuleMetadata: {
ExitCode = doPrintModuleMetaData(InitInvok, options::ModuleToPrint);
break;
}
case ActionType::PrintHeader: {
ExitCode = doPrintHeaders(
InitInvok, options::HeaderToPrint, PrintOpts,
options::AnnotatePrint);
break;
}
case ActionType::PrintSwiftFileInterface: {
ExitCode = doPrintSwiftFileInterface(
InitInvok, options::SourceFilename,
options::AnnotatePrint);
break;
}
case ActionType::PrintDecl: {
ExitCode = doPrintDecls(
InitInvok, options::SourceFilename,
options::DeclToPrint, PrintOpts, options::AnnotatePrint);
break;
}
case ActionType::PrintTypes:
ExitCode = doPrintTypes(InitInvok, options::SourceFilename,
options::FullyQualifiedTypes);
break;
case ActionType::PrintComments:
ExitCode = doPrintComments(InitInvok, options::SourceFilename,
options::CommentsXMLSchema);
break;
case ActionType::DumpComments:
ExitCode = doDumpComments(InitInvok, options::SourceFilename);
break;
case ActionType::PrintModuleComments:
ExitCode = doPrintModuleComments(InitInvok, options::ModuleToPrint,
options::CommentsXMLSchema);
break;
case ActionType::PrintModuleImports:
ExitCode = doPrintModuleImports(InitInvok, options::ModuleToPrint);
break;
case ActionType::PrintUSRs:
ExitCode = doPrintUSRs(InitInvok, options::SourceFilename);
break;
case ActionType::PrintTypeInterface:
if (options::LineColumnPair.getNumOccurrences() == 1)
ExitCode = doPrintTypeInterface(InitInvok,
options::SourceFilename,
options::LineColumnPair);
else
ExitCode = doPrintTypeInterfaceForTypeUsr(InitInvok,
options::SourceFilename,
options::USR);
break;
case ActionType::ReconstructType:
ExitCode = doReconstructType(InitInvok, options::SourceFilename);
break;
case ActionType::Range:
ExitCode = doPrintRangeInfo(InitInvok, options::SourceFilename,
options::LineColumnPair,
options::EndLineColumnPair);
break;
case ActionType::PrintIndexedSymbols:
if (options::ModuleToPrint.empty()) {
ExitCode = doPrintIndexedSymbols(InitInvok, options::SourceFilename,
options::IncludeLocals);
} else {
if (options::ModuleToPrint.size() > 1) {
llvm::errs() << "printing symbols for the first module name, the rest "
"are ignored";
}
ExitCode = doPrintIndexedSymbolsFromModule(InitInvok,
options::ModuleToPrint.front());
}
}
if (options::PrintStats)
llvm::PrintStatistics();
return ExitCode;
}