export function activate(activationEventOccurred: boolean): void { if (realActivationOccurred) { return; // Occurs if multiple delayed commands occur before the real commands are registered. } // Activate immediately if an activation event occurred in the previous workspace session. // If onActivationEvent doesn't occur, it won't auto-activate next time. activatedPreviously = new PersistentWorkspaceState("activatedPreviously", false); if (activatedPreviously.Value) { activatedPreviously.Value = false; realActivation(); } if (tempCommands.length === 0) { // Only needs to be added once. tempCommands.push(vscode.workspace.onDidOpenTextDocument(d => onDidOpenTextDocument(d))); } // Check if an activation event has already occurred. if (activationEventOccurred) { onActivationEvent(); return; } taskProvider = vscode.tasks.registerTaskProvider(taskSourceStr, { provideTasks: () => { return getBuildTasks(false); }, resolveTask(task: vscode.Task): vscode.Task { // Currently cannot implement because VS Code does not call this. Can implement custom output file directory when enabled. return undefined; } }); vscode.tasks.onDidStartTask(event => { if (event.execution.task.source === taskSourceStr) { telemetry.logLanguageServerEvent('buildTaskStarted'); } }); // handle "workspaceContains:/.vscode/c_cpp_properties.json" activation event. if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) { for (let i: number = 0; i < vscode.workspace.workspaceFolders.length; ++i) { let config: string = path.join(vscode.workspace.workspaceFolders[i].uri.fsPath, ".vscode/c_cpp_properties.json"); if (fs.existsSync(config)) { onActivationEvent(); return; } } } // handle "onLanguage:cpp" and "onLanguage:c" activation events. if (vscode.workspace.textDocuments !== undefined && vscode.workspace.textDocuments.length > 0) { for (let i: number = 0; i < vscode.workspace.textDocuments.length; ++i) { let document: vscode.TextDocument = vscode.workspace.textDocuments[i]; if (document.languageId === "cpp" || document.languageId === "c") { onActivationEvent(); return; } } } }
function runTest(sourceUri: string, className: string, methodName: string): Thenable<TaskExecution> { let file = Uri.parse(sourceUri).fsPath; file = Path.relative(workspace.rootPath, file); let kind: JavaTestTask = { type: 'java.task.test', className: className, methodName: methodName, } var shell; let config = workspace.getConfiguration('java') // Run method or class if (methodName != null) { let command = config.get('testMethod') as string[] if (command.length == 0) { window.showErrorMessage('Set "java.testMethod" in .vscode/settings.json') shell = new ShellExecution('echo', ['Set "java.testMethod" in .vscode/settings.json, for example ["mvn", "test", "-Dtest=${class}#${method}"]']) } else { shell = templateCommand(command, file, className, methodName) } } else { let command = config.get('testClass') as string[] if (command.length == 0) { window.showErrorMessage('Set "java.testClass" in .vscode/settings.json') shell = new ShellExecution('echo', ['Set "java.testClass" in .vscode/settings.json, for example ["mvn", "test", "-Dtest=${class}"]']) } else { shell = templateCommand(command, file, className, methodName) } } let workspaceFolder = workspace.getWorkspaceFolder(Uri.parse(sourceUri)) let task = new Task(kind, workspaceFolder, 'Java Test', 'Java Language Server', shell) return tasks.executeTask(task) }
export function activate(context: vscode.ExtensionContext) { let taskCommand: string = null; let problemMatcher: string = null; const outputChannel = vscode.window.createOutputChannel("phpunit"); const PHPUnitTestRunner: TestRunner = new TestRunner(outputChannel, { setTaskCommand: (command: string, matcher?: string) => { taskCommand = command; problemMatcher = matcher; } }); context.subscriptions.push( vscode.commands.registerCommand("phpunit.Test", () => { PHPUnitTestRunner.run("test"); }) ); context.subscriptions.push( vscode.commands.registerCommand("phpunit.TestNearest", () => { PHPUnitTestRunner.run("nearest-test"); }) ); context.subscriptions.push( vscode.commands.registerCommand("phpunit.TestDirectory", () => { PHPUnitTestRunner.run("directory"); }) ); context.subscriptions.push( vscode.commands.registerCommand("phpunit.RerunLastTest", () => { PHPUnitTestRunner.run("rerun-last-test"); }) ); context.subscriptions.push( vscode.commands.registerCommand("phpunit.TestingStop", () => { PHPUnitTestRunner.stop(); }) ); context.subscriptions.push( vscode.tasks.registerTaskProvider("phpunit", { provideTasks: () => { return [ new vscode.Task( { type: "phpunit", task: "run" }, vscode.TaskScope.Workspace, "run", "phpunit", new vscode.ShellExecution(taskCommand), problemMatcher || "$phpunit" ) ]; }, resolveTask: undefined }) ); }
export function runScript(script: string, document: TextDocument) { let uri = document.uri; let folder = workspace.getWorkspaceFolder(uri); if (folder) { let task = createTask(script, `run ${script}`, folder, uri); tasks.executeTask(task); } }
public runScriptFromHover(args: any) { let script = args.script; let documentUri = args.documentUri; let folder = workspace.getWorkspaceFolder(documentUri); if (folder) { let task = createTask(script, `run ${script}`, folder, documentUri); tasks.executeTask(task); } }
export function activateTaskProvider(target: WorkspaceFolder): Disposable { const provider: TaskProvider = { provideTasks: function () { // npm or others parse their task definitions. So they need to provide 'autoDetect' feature. // e,g, https://github.com/Microsoft/vscode/blob/de7e216e9ebcad74f918a025fc5fe7bdbe0d75b2/extensions/npm/src/main.ts // However, cargo.toml does not support to define a new task like them. // So we are not 'autoDetect' feature and the setting for it. return getCargoTasks(target); }, resolveTask(_task: Task): Task | undefined { return undefined; } }; return tasks.registerTaskProvider('cargo', provider); }
export function runCommand(folder: WorkspaceFolder, cmd: Cmd): Thenable<TaskExecution> { const config: TaskConfigItem = { definition: { label: 'run Cargo command', type: 'cargo', command: cmd.binary, args: cmd.args, env: cmd.env, }, problemMatcher: ['$rustc'], group: TaskGroup.Build, presentationOptions: { reveal: TaskRevealKind.Always, panel: TaskPanelKind.Dedicated, }, }; const task = createTask(config, folder); return tasks.executeTask(task); }
export function activate(_context: vscode.ExtensionContext): void { let workspaceRoot = vscode.workspace.rootPath; if (!workspaceRoot) { return; } let pattern = path.join(workspaceRoot, 'Rakefile'); let rakePromise: Thenable<vscode.Task[]> | undefined = undefined; let fileWatcher = vscode.workspace.createFileSystemWatcher(pattern); fileWatcher.onDidChange(() => rakePromise = undefined); fileWatcher.onDidCreate(() => rakePromise = undefined); fileWatcher.onDidDelete(() => rakePromise = undefined); taskProvider = vscode.tasks.registerTaskProvider('rake', { provideTasks: () => { if (!rakePromise) { rakePromise = getRakeTasks(); } return rakePromise; }, resolveTask(_task: vscode.Task): vscode.Task | undefined { return undefined; } }); }
export function activate(context: vs.ExtensionContext, isRestart: boolean = false) { if (!extensionLogger) extensionLogger = logTo(getExtensionLogPath(), [LogCategory.General]); const extContext = Context.for(context); util.logTime("Code called activate"); // Wire up a reload command that will re-initialise everything. context.subscriptions.push(vs.commands.registerCommand("_dart.reloadExtension", (_) => { log("Performing silent extension reload..."); deactivate(true); const toDispose = context.subscriptions.slice(); context.subscriptions.length = 0; for (const sub of toDispose) { try { sub.dispose(); } catch (e) { logError(e); } } activate(context, true); log("Done!"); })); showTodos = config.showTodos; previousSettings = getSettingsThatRequireRestart(); extensionPath = context.extensionPath; const extensionStartTime = new Date(); util.logTime(); const workspaceContext = initWorkspace(); util.logTime("initWorkspace"); const sdks = workspaceContext.sdks; buildLogHeaders(workspaceContext); analytics = new Analytics(workspaceContext); if (!sdks.dart || (workspaceContext.hasAnyFlutterProjects && !sdks.flutter)) { // Don't set anything else up; we can't work like this! return handleMissingSdks(context, analytics, workspaceContext); } if (sdks.flutterVersion) flutterCapabilities.version = sdks.flutterVersion; // Show the SDK version in the status bar. if (sdks.dartVersion) { dartCapabilities.version = sdks.dartVersion; analytics.sdkVersion = sdks.dartVersion; checkForStandardDartSdkUpdates(workspaceContext); context.subscriptions.push(new StatusBarVersionTracker(workspaceContext)); } // Fire up the analyzer process. const analyzerStartTime = new Date(); const analyzerPath = config.analyzerPath || path.join(sdks.dart, analyzerSnapshotPath); // If the ssh host is set, then we are running the analyzer on a remote machine, that same analyzer // might not exist on the local machine. if (!config.analyzerSshHost && !fs.existsSync(analyzerPath)) { vs.window.showErrorMessage("Could not find a Dart Analysis Server at " + analyzerPath); return; } analyzer = new Analyzer(path.join(sdks.dart, dartVMPath), analyzerPath); context.subscriptions.push(analyzer); // Log analysis server startup time when we get the welcome message/version. const connectedEvents = analyzer.registerForServerConnected((sc) => { analytics.analysisServerVersion = sc.version; const analyzerEndTime = new Date(); analytics.logAnalyzerStartupTime(analyzerEndTime.getTime() - analyzerStartTime.getTime()); connectedEvents.dispose(); }); const nextAnalysis = () => new Promise<void>((resolve, reject) => { const disposable = analyzer.registerForServerStatus((ss) => { if (ss.analysis && !ss.analysis.isAnalyzing) { resolve(); disposable.dispose(); } }); }); // Log analysis server first analysis completion time when it completes. let analysisStartTime: Date; const initialAnalysis = nextAnalysis(); const analysisCompleteEvents = analyzer.registerForServerStatus((ss) => { // Analysis started for the first time. if (ss.analysis && ss.analysis.isAnalyzing && !analysisStartTime) analysisStartTime = new Date(); // Analysis ends for the first time. if (ss.analysis && !ss.analysis.isAnalyzing && analysisStartTime) { const analysisEndTime = new Date(); analytics.logAnalyzerFirstAnalysisTime(analysisEndTime.getTime() - analysisStartTime.getTime()); analysisCompleteEvents.dispose(); } }); // Set up providers. // TODO: Do we need to push all these to subscriptions?! const hoverProvider = new DartHoverProvider(analyzer); const formattingEditProvider = new DartFormattingEditProvider(analyzer, extContext); context.subscriptions.push(formattingEditProvider); const completionItemProvider = new DartCompletionItemProvider(analyzer); const referenceProvider = new DartReferenceProvider(analyzer); const documentHighlightProvider = new DartDocumentHighlightProvider(analyzer); const sourceCodeActionProvider = new SourceCodeActionProvider(); const renameProvider = new DartRenameProvider(analyzer); const implementationProvider = new DartImplementationProvider(analyzer); const activeFileFilters = [DART_MODE]; if (config.analyzeAngularTemplates && analyzer.capabilities.supportsAnalyzingHtmlFiles) { // Analyze Angular2 templates, requires the angular_analyzer_plugin. activeFileFilters.push(HTML_MODE); } // This is registered with VS Code further down, so it's metadata can be collected from all // registered providers. const rankingCodeActionProvider = new RankingCodeActionProvider(); const triggerCharacters = ".(${'\"/\\".split(""); context.subscriptions.push(vs.languages.registerHoverProvider(activeFileFilters, hoverProvider)); formattingEditProvider.registerDocumentFormatter(activeFileFilters); context.subscriptions.push(vs.languages.registerCompletionItemProvider(activeFileFilters, completionItemProvider, ...triggerCharacters)); context.subscriptions.push(vs.languages.registerDefinitionProvider(activeFileFilters, referenceProvider)); context.subscriptions.push(vs.languages.registerReferenceProvider(activeFileFilters, referenceProvider)); context.subscriptions.push(vs.languages.registerDocumentHighlightProvider(activeFileFilters, documentHighlightProvider)); rankingCodeActionProvider.registerProvider(new AssistCodeActionProvider(activeFileFilters, analyzer)); rankingCodeActionProvider.registerProvider(new FixCodeActionProvider(activeFileFilters, analyzer)); rankingCodeActionProvider.registerProvider(new RefactorCodeActionProvider(activeFileFilters, analyzer)); context.subscriptions.push(vs.languages.registerRenameProvider(activeFileFilters, renameProvider)); // Some actions only apply to Dart. formattingEditProvider.registerTypingFormatter(DART_MODE, "}", ";"); context.subscriptions.push(vs.languages.registerCodeActionsProvider(DART_MODE, sourceCodeActionProvider, sourceCodeActionProvider.metadata)); rankingCodeActionProvider.registerProvider(new IgnoreLintCodeActionProvider(activeFileFilters)); context.subscriptions.push(vs.languages.registerImplementationProvider(DART_MODE, implementationProvider)); if (config.showTestCodeLens) { const codeLensProvider = new TestCodeLensProvider(analyzer); context.subscriptions.push(codeLensProvider); context.subscriptions.push(vs.languages.registerCodeLensProvider(DART_MODE, codeLensProvider)); } // Register the ranking provider from VS Code now that it has all of its delegates. context.subscriptions.push(vs.languages.registerCodeActionsProvider(activeFileFilters, rankingCodeActionProvider, rankingCodeActionProvider.metadata)); // Task handlers. if (config.previewBuildRunnerTasks) { context.subscriptions.push(vs.tasks.registerTaskProvider("pub", new PubBuildRunnerTaskProvider(sdks))); } // Snippets are language-specific context.subscriptions.push(vs.languages.registerCompletionItemProvider(DART_MODE, new SnippetCompletionItemProvider("snippets/dart.json", (_) => true))); context.subscriptions.push(vs.languages.registerCompletionItemProvider(DART_MODE, new SnippetCompletionItemProvider("snippets/flutter.json", (uri) => util.isInsideFlutterProject(uri)))); context.subscriptions.push(vs.languages.setLanguageConfiguration(DART_MODE.language, new DartLanguageConfiguration())); const statusReporter = new AnalyzerStatusReporter(analyzer, workspaceContext, analytics); // Set up diagnostics. const diagnostics = vs.languages.createDiagnosticCollection("dart"); context.subscriptions.push(diagnostics); const diagnosticsProvider = new DartDiagnosticProvider(analyzer, diagnostics); // Set the roots, handling project changes that might affect SDKs. context.subscriptions.push(vs.workspace.onDidChangeWorkspaceFolders((f) => recalculateAnalysisRoots())); // TODO: Currently calculating analysis roots requires the version to check if // we need the package workaround. In future if we stop supporting server < 1.20.1 we // can unwrap this call so that it'll start sooner. const serverConnected = analyzer.registerForServerConnected((sc) => { serverConnected.dispose(); if (vs.workspace.workspaceFolders) recalculateAnalysisRoots(); }); // Hook editor changes to send updated contents to analyzer. context.subscriptions.push(new FileChangeHandler(analyzer)); // Fire up Flutter daemon if required. if (workspaceContext.hasAnyFlutterMobileProjects) { flutterDaemon = new FlutterDaemon(path.join(sdks.flutter, flutterPath), sdks.flutter); context.subscriptions.push(flutterDaemon); setUpDaemonMessageHandler(context, flutterDaemon); } util.logTime("All other stuff before debugger.."); const pubGlobal = new PubGlobal(extContext, sdks); // Set up debug stuff. const debugProvider = new DebugConfigProvider(sdks, analytics, pubGlobal, flutterDaemon && flutterDaemon.deviceManager, flutterCapabilities); context.subscriptions.push(vs.debug.registerDebugConfigurationProvider("dart", debugProvider)); context.subscriptions.push(debugProvider); // Setup that requires server version/capabilities. const connectedSetup = analyzer.registerForServerConnected((sc) => { connectedSetup.dispose(); if (analyzer.capabilities.supportsClosingLabels && config.closingLabels) { context.subscriptions.push(new ClosingLabelsDecorations(analyzer)); } if (analyzer.capabilities.supportsGetDeclerations) { context.subscriptions.push(vs.languages.registerWorkspaceSymbolProvider(new DartWorkspaceSymbolProvider(analyzer))); } else { context.subscriptions.push(vs.languages.registerWorkspaceSymbolProvider(new LegacyDartWorkspaceSymbolProvider(analyzer))); } if (analyzer.capabilities.supportsCustomFolding && config.analysisServerFolding) context.subscriptions.push(vs.languages.registerFoldingRangeProvider(DART_MODE, new DartFoldingProvider(analyzer))); if (analyzer.capabilities.supportsGetSignature) context.subscriptions.push(vs.languages.registerSignatureHelpProvider( DART_MODE, new DartSignatureHelpProvider(analyzer), ...(config.triggerSignatureHelpAutomatically ? ["(", ","] : []), )); const documentSymbolProvider = new DartDocumentSymbolProvider(analyzer); activeFileFilters.forEach((filter) => { context.subscriptions.push(vs.languages.registerDocumentSymbolProvider(filter, documentSymbolProvider)); }); context.subscriptions.push(new OpenFileTracker(analyzer)); // Set up completions for unimported items. if (analyzer.capabilities.supportsAvailableSuggestions && config.autoImportCompletions) { analyzer.completionSetSubscriptions({ subscriptions: ["AVAILABLE_SUGGESTION_SETS"], }); } }); // Handle config changes so we can reanalyze if necessary. context.subscriptions.push(vs.workspace.onDidChangeConfiguration(() => handleConfigurationChange(sdks))); context.subscriptions.push(vs.workspace.onDidSaveTextDocument((td) => { if (path.basename(fsPath(td.uri)).toLowerCase() === "pubspec.yaml") handleConfigurationChange(sdks); })); // Handle project changes that might affect SDKs. context.subscriptions.push(vs.workspace.onDidChangeWorkspaceFolders((f) => { handleConfigurationChange(sdks); })); // Register additional commands. const analyzerCommands = new AnalyzerCommands(context, analyzer); const sdkCommands = new SdkCommands(context, workspaceContext, pubGlobal, flutterCapabilities, flutterDaemon && flutterDaemon.deviceManager); const debugCommands = new DebugCommands(extContext, workspaceContext, analytics, pubGlobal); // Wire up handling of Hot Reload on Save. if (workspaceContext.hasAnyFlutterProjects) { setUpHotReloadOnSave(context, diagnostics, debugCommands); } // Register URI handler. context.subscriptions.push(vs.window.registerUriHandler(new DartUriHandler(flutterCapabilities))); // Set up commands for Dart editors. context.subscriptions.push(new EditCommands(context, analyzer)); context.subscriptions.push(new RefactorCommands(context, analyzer)); // Register misc commands. context.subscriptions.push(new TypeHierarchyCommand(analyzer)); context.subscriptions.push(new GoToSuperCommand(analyzer)); context.subscriptions.push(new LoggingCommands(context.logPath)); context.subscriptions.push(new OpenInOtherEditorCommands(sdks)); context.subscriptions.push(new TestCommands()); // Register our view providers. const dartPackagesProvider = new DartPackagesProvider(); const packagesTreeView = vs.window.createTreeView("dartPackages", { treeDataProvider: dartPackagesProvider }); context.subscriptions.push( dartPackagesProvider, packagesTreeView, ); context.subscriptions.push(vs.workspace.onDidChangeWorkspaceFolders((f) => { dartPackagesProvider.refresh(); })); const testTreeProvider = new TestResultsProvider(); const testTreeView = vs.window.createTreeView("dartTestTree", { treeDataProvider: testTreeProvider }); context.subscriptions.push( testTreeProvider, testTreeView, testTreeProvider.onDidStartTests((node) => { if (config.openTestViewOnStart) testTreeView.reveal(node); }), testTreeProvider.onFirstFailure((node) => { if (config.openTestViewOnFailure) testTreeView.reveal(node); }), testTreeView.onDidChangeSelection((e) => { testTreeProvider.setSelectedNodes(e.selection && e.selection.length === 1 ? e.selection[0] : undefined); }), ); if (workspaceContext.hasAnyFlutterProjects && config.previewHotReloadCoverageMarkers) { context.subscriptions.push(new HotReloadCoverageDecorations(debugCommands)); } context.subscriptions.push(vs.commands.registerCommand("dart.package.openFile", (filePath) => { if (!filePath) return; vs.workspace.openTextDocument(filePath).then((document) => { vs.window.showTextDocument(document, { preview: true }); }, (error) => logError(error)); })); // Warn the user if they've opened a folder with mismatched casing. if (vs.workspace.workspaceFolders && vs.workspace.workspaceFolders.length) { for (const wf of vs.workspace.workspaceFolders) { const userPath = forceWindowsDriveLetterToUppercase(fsPath(wf.uri)); const realPath = forceWindowsDriveLetterToUppercase(util.trueCasePathSync(userPath)); if (userPath && realPath && userPath !== realPath) { vs.window.showWarningMessage( `The casing of the open workspace folder does not match the casing on the underlying disk; please re-open the folder using the File Open dialog. ` + `Expected ${realPath} but got ${userPath}`, ); break; } } } // Prompt user for any special config we might want to set. if (!isRestart) showUserPrompts(extContext, workspaceContext); // Turn on all the commands. setCommandVisiblity(true, workspaceContext); vs.commands.executeCommand("setContext", DART_PLATFORM_NAME, dartPlatformName); // Prompt for pub get if required function checkForPackages() { // Don't prompt for package updates in the Fuchsia tree. if (workspaceContext.hasProjectsInFuchsiaTree) // TODO: This should be tested per-project. return; const folders = util.getDartWorkspaceFolders(); const foldersRequiringPackageGet = folders.filter((ws: vs.WorkspaceFolder) => config.for(ws.uri).promptToGetPackages).filter(isPubGetProbablyRequired); if (foldersRequiringPackageGet.length > 0) promptToRunPubGet(foldersRequiringPackageGet); } context.subscriptions.push(vs.workspace.onDidChangeWorkspaceFolders((f) => checkForPackages())); if (!isRestart) checkForPackages(); // Begin activating dependant packages. if (workspaceContext.shouldLoadFlutterExtension) { const flutterExtension = vs.extensions.getExtension(flutterExtensionIdentifier); if (flutterExtension) { log(`Activating Flutter extension for ${workspaceContext.workspaceTypeDescription} project...`); flutterExtension.activate(); } } // Log how long all this startup took. const extensionEndTime = new Date(); if (isRestart) { analytics.logExtensionRestart(extensionEndTime.getTime() - extensionStartTime.getTime()); } else { analytics.logExtensionStartup(extensionEndTime.getTime() - extensionStartTime.getTime()); } return { ...new DartExtensionApi(), [internalApiSymbol]: { analyzerCapabilities: analyzer.capabilities, cancelAllAnalysisRequests: () => analyzer.cancelAllRequests(), completionItemProvider, context: extContext, currentAnalysis: () => analyzer.currentAnalysis, daemonCapabilities: flutterDaemon ? flutterDaemon.capabilities : DaemonCapabilities.empty, dartCapabilities, debugCommands, debugProvider, flutterCapabilities, initialAnalysis, nextAnalysis, packagesTreeProvider: dartPackagesProvider, pubGlobal, reanalyze, referenceProvider, renameProvider, testTreeProvider, workspaceContext, } as InternalExtensionApi, }; }