Example #1
0
export function activate(context: ExtensionContext) {
    const { fileIsIgnored } = ignoreFileHandler(context.subscriptions);
    const editProvider = new EditProvider(fileIsIgnored);
    function registerFormatter() {
        disposeHandlers();
        const { languageSelector, rangeLanguageSelector } = selectors();
        rangeFormatterHandler = languages.registerDocumentRangeFormattingEditProvider(
            rangeLanguageSelector,
            editProvider
        );
        formatterHandler = languages.registerDocumentFormattingEditProvider(
            languageSelector,
            editProvider
        );
    }
    registerFormatter();
    context.subscriptions.push(
        workspace.onDidChangeWorkspaceFolders(registerFormatter),
        {
            dispose: disposeHandlers,
        },
        setupErrorHandler(),
        configFileListener(),
        ...registerDisposables()
    );
}
Example #2
0
function registerTaskProvider(context: vscode.ExtensionContext): vscode.Disposable | undefined {

	function invalidateScriptCaches() {
		invalidateHoverScriptsCache();
		invalidateTasksCache();
		if (treeDataProvider) {
			treeDataProvider.refresh();
		}
	}

	if (vscode.workspace.workspaceFolders) {
		let watcher = vscode.workspace.createFileSystemWatcher('**/package.json');
		watcher.onDidChange((_e) => invalidateScriptCaches());
		watcher.onDidDelete((_e) => invalidateScriptCaches());
		watcher.onDidCreate((_e) => invalidateScriptCaches());
		context.subscriptions.push(watcher);

		let workspaceWatcher = vscode.workspace.onDidChangeWorkspaceFolders((_e) => invalidateScriptCaches());
		context.subscriptions.push(workspaceWatcher);

		let provider: vscode.TaskProvider = new NpmTaskProvider();
		let disposable = vscode.workspace.registerTaskProvider('npm', provider);
		context.subscriptions.push(disposable);
		return disposable;
	}
	return undefined;
}
Example #3
0
function createWatcher( func: (e: Uri)=>void, extension: string ): void {
    var dict: any[] = [];
    
        function addWatcher(wf: WorkspaceFolder) {
            var watcher = workspace.createFileSystemWatcher( new RelativePattern(wf, `**/*.${extension}` ) );  
            dict.push({key: wf.uri.fsPath, value: watcher});
            watcher.onDidCreate( (e) => {
                func( e );
                // cmUtils.addCopyright( e );
            } );
        }
    
        workspace.workspaceFolders.forEach( wf => {
           addWatcher( wf );
        });
    
        workspace.onDidChangeWorkspaceFolders( e => {
            e.added.forEach( a => {
                addWatcher(a);
            });
            e.removed.forEach( a => {
                let watcher: FileSystemWatcher = dict.find( o => o.key == a.uri.fsPath );
                watcher = null;
            })
        } );
}
export function activate(context: ExtensionContext) {

    // Create a status bar item
    const status = window.createStatusBarItem(StatusBarAlignment.Left, 1000000);
    context.subscriptions.push(status);

    // Update status bar item based on events for multi root folder changes
    context.subscriptions.push(workspace.onDidChangeWorkspaceFolders(e => updateStatus(status)));

    // Update status bar item based on events for configuration
    context.subscriptions.push(workspace.onDidChangeConfiguration(e => this.updateStatus(status)));

    // Update status bar item based on events around the active editor
    context.subscriptions.push(window.onDidChangeActiveTextEditor(e => updateStatus(status)));
    context.subscriptions.push(window.onDidChangeTextEditorViewColumn(e => updateStatus(status)));
    context.subscriptions.push(workspace.onDidOpenTextDocument(e => updateStatus(status)));
    context.subscriptions.push(workspace.onDidCloseTextDocument(e => updateStatus(status)));

    updateStatus(status);
}
Example #5
0
export function activate(ctx: vscode.ExtensionContext) {
  const elixirSetting = vscode.workspace.getConfiguration('elixir');
  useElixirSense = elixirSetting.useElixirSense;
  autoSpawnElixirSenseServers = elixirSetting.autoSpawnElixirSenseServers;
  const projectPath = elixirSetting.projectPath;
  // TODO: detect environment automatically.
  const env = elixirSetting.elixirEnv;

  if (useElixirSense) {
    ElixirSenseServerProcess.initClass();
    if (autoSpawnElixirSenseServers) {
      (vscode.workspace.workspaceFolders || []).forEach(workspaceFolder => {
        startElixirSenseServerForWorkspaceFolder(workspaceFolder, ctx, env, projectPath);
      });
    } else if ((vscode.workspace.workspaceFolders || []).length === 1) {
      startElixirSenseServerForWorkspaceFolder(vscode.workspace.workspaceFolders[0], ctx, env);
    }
    vscode.workspace.onDidChangeWorkspaceFolders(e => {
      (e.removed || []).forEach(workspaceFolder => stopElixirSenseServerByPath(workspaceFolder.uri.fsPath));
      if (autoSpawnElixirSenseServers) {
        (e.added || []).forEach(workspaceFolder => startElixirSenseServerForWorkspaceFolder(workspaceFolder, ctx, env));
      }
    });
  } else {
    this.elixirServer = new ElixirServer(elixirSetting.command);
    this.elixirServer.start();
    ctx.subscriptions.push(vscode.languages.registerCompletionItemProvider(ELIXIR_MODE, new ElixirAutocomplete(this.elixirServer), '.'));
    ctx.subscriptions.push(vscode.languages.registerDefinitionProvider(ELIXIR_MODE, new ElixirDefinitionProvider(this.elixirServer)));
    ctx.subscriptions.push(vscode.languages.registerHoverProvider(ELIXIR_MODE, new ElixirHoverProvider(this.elixirServer)));
    ctx.subscriptions.push(vscode.languages.registerDocumentFormattingEditProvider(ELIXIR_MODE, new ElixirFormatterProvider()));
    ctx.subscriptions.push(vscode.languages.setLanguageConfiguration('elixir', configuration));
  }

  ctx.subscriptions.push(vscode.languages.registerDocumentSymbolProvider({ language: 'elixir' }, new ElixirDocumentSymbolProvider()));

  const disposables = [];
  if (useElixirSense) {
    disposables.push(vscode.commands.registerCommand('extension.selectElixirSenseWorkspaceFolder', () => selectElixirSenseWorkspaceFolder(ctx, env)));
  }
  ctx.subscriptions.push(...disposables);
}
export function activate(context: vscode.ExtensionContext) {

    let riolog = new RioLog();
    context.subscriptions.push(riolog);

    let preferences: Preferences[] = [];

    let workspaces = vscode.workspace.workspaceFolders;

    if (workspaces === undefined) {
        vscode.window.showErrorMessage('WPILib does not support single file');
        return;
    }

    for (let w of workspaces) {
        preferences.push(new Preferences(w));
    }

    context.subscriptions.push(vscode.workspace.onDidChangeWorkspaceFolders(() => {
        // Nuke and restart
        for (let p of preferences) {
            p.dispose();
        }
        let wp = vscode.workspace.workspaceFolders;

        if (wp === undefined) {
            return;
        }

        for (let w of wp) {
            preferences.push(new Preferences(w));
        }
    }));

    context.subscriptions.push(...preferences);

    let extensionResourceLocation = path.join(context.extensionPath, 'resources');

    let tools = new Array<IToolRunner>();
    let codeDeployers = new Array<ICodeDeployer>();
    let codeDebuggers = new Array<ICodeDeployer>();
    let languageChoices = new Array<string>();

    let api : IExternalAPI = {
        async startRioLog(teamNumber: number) : Promise<void> {
            riolog.connect(teamNumber, path.join(extensionResourceLocation, 'riolog'));
        },
        async startTool(): Promise<void> {
            if (tools.length <= 0) {
                vscode.window.showErrorMessage('No tools found. Please install some');
                return;
            }

            let toolNames = new Array<string>();
            for (let t of tools) {
                toolNames.push(t.getDisplayName());
            }

            let result = await vscode.window.showQuickPick(toolNames, { placeHolder: 'Pick a tool'});

            if (result === undefined) {
                vscode.window.showInformationMessage('Tool run canceled');
                return;
            }

            for (let t of tools) {
                if (t.getDisplayName() === result) {
                    await t.runTool();
                    return;
                }
            }

            vscode.window.showErrorMessage('Invalid tool entered');
            return;
        },
        addTool(tool: IToolRunner): void {
            tools.push(tool);
        },
        async deployCode(workspace: vscode.WorkspaceFolder): Promise<boolean> {
            if (codeDeployers.length <= 0) {
                vscode.window.showErrorMessage('No registered deployers');
                return false;
            }

            let prefs = await this.getPreferences(workspace);

            let availableDeployers = new Array<ICodeDeployer>();
            for (let d of codeDeployers) {
                if (await d.getIsCurrentlyValid(workspace)) {
                    availableDeployers.push(d);
                }
            }

            if (availableDeployers.length <= 0) {
                vscode.window.showErrorMessage('No registered deployers');
                return false;
            } else if (availableDeployers.length === 1) {
                if (prefs.getAutoSaveOnDeploy()) {
                    vscode.workspace.saveAll();
                }
                let teamNumber = await prefs.getTeamNumber();
                let ret = await availableDeployers[0].runDeployer(teamNumber, workspace);
                if (prefs.getAutoStartRioLog() && ret) {
                    await this.startRioLog(teamNumber);
                }
                return ret;
            } else {
                let names = new Array<string>();
                for (let d of availableDeployers) {
                    names.push(d.getDisplayName());
                }
                let result = await vscode.window.showQuickPick(names, {placeHolder: 'Pick a deploy language'});
                if (result === undefined) {
                    await vscode.window.showInformationMessage('Deploy exited');
                    return false;
                }

                for (let d of availableDeployers) {
                    if (d.getDisplayName() === result) {
                        if (prefs.getAutoSaveOnDeploy()) {
                            vscode.workspace.saveAll();
                        }
                        let teamNumber = await prefs.getTeamNumber();
                        let ret = await d.runDeployer(teamNumber, workspace);
                        if (prefs.getAutoStartRioLog() && ret) {
                            await this.startRioLog(teamNumber);
                        }
                        return ret;
                    }
                }

                await vscode.window.showInformationMessage('Deploy exited');
                return false;
            }
        },
        registerCodeDeploy(deployer: ICodeDeployer): void {
            codeDeployers.push(deployer);
        },
        async debugCode(workspace: vscode.WorkspaceFolder): Promise<boolean> {
            if (codeDebuggers.length <= 0) {
                vscode.window.showErrorMessage('No registered debuggers');
                return false;
            }

            let availableDebuggers = new Array<ICodeDeployer>();
            for (let d of codeDebuggers) {
                if (await d.getIsCurrentlyValid(workspace)) {
                    availableDebuggers.push(d);
                }
            }

            if (availableDebuggers.length <= 0) {
                vscode.window.showErrorMessage('No registered debuggers');
                return false;
            } else if (availableDebuggers.length === 1) {
                let prefs = this.getPreferences(workspace);
                if (prefs.getAutoSaveOnDeploy()) {
                    vscode.workspace.saveAll();
                }
                await availableDebuggers[0].runDeployer(await prefs.getTeamNumber(), workspace);
            } else {
                let names = new Array<string>();
                for (let d of availableDebuggers) {
                    names.push(d.getDisplayName());
                }
                let result = await vscode.window.showQuickPick(names, { placeHolder: 'Pick a debug language'});
                if (result === undefined) {
                    await vscode.window.showInformationMessage('Debug exited');
                    return false;
                }

                for (let d of availableDebuggers) {
                    if (d.getDisplayName() === result) {
                        let prefs = this.getPreferences(workspace);
                        if (prefs.getAutoSaveOnDeploy()) {
                            vscode.workspace.saveAll();
                        }
                        return await d.runDeployer(await prefs.getTeamNumber(), workspace);
                    }
                }

                await vscode.window.showInformationMessage('Debug exited');
                return false;
            }
            return false;
        },
        registerCodeDebug(deployer: ICodeDeployer): void {
            codeDebuggers.push(deployer);
        },
        getApiVersion(): number {
            return 1;
        },
        getPreferences(workspace: vscode.WorkspaceFolder): IPreferences {
            for (let p of preferences) {
                if (p.workspace.uri === workspace.uri) {
                    return p;
                }
            }
            return preferences[0];
        },
        addLanguageChoice(language: string): void {
            languageChoices.push(language);
        },
        async requestLanguageChoice(): Promise<string> {
            if (languageChoices.length <= 0) {
                return '';
            }
            let result = await vscode.window.showQuickPick(languageChoices, { placeHolder: 'Pick a language' } );
            if (result === undefined) {
                return '';
            }
            return result;
        },
        async getFirstOrSelectedWorkspace(): Promise<vscode.WorkspaceFolder | undefined> {
            let wp = vscode.workspace.workspaceFolders;
            if (wp === undefined) {
                return;
            }
            let workspace = wp[0];
            if (wp.length > 1) {
                let res = await vscode.window.showWorkspaceFolderPick();
                if (res !== undefined) {
                    workspace = res;
                }
            }
            return workspace;
        }
    };

    // Use the console to output diagnostic information (console.log) and errors (console.error)
    // This line of code will only be executed once when your extension is activated
    console.log('Congratulations, your extension "vscode-wpilib-core" is now active!');

    context.subscriptions.push(vscode.commands.registerCommand('wpilibcore.startRioLog', async () =>{
        let workspace = await api.getFirstOrSelectedWorkspace();
        if (workspace === undefined) {
            return;
        }
        await api.startRioLog(await api.getPreferences(workspace).getTeamNumber());
    }));

    context.subscriptions.push(vscode.commands.registerCommand('wpilibcore.setTeamNumber', async () =>{
        let workspace = await api.getFirstOrSelectedWorkspace();
        if (workspace === undefined) {
            return;
        }
        await api.getPreferences(workspace).setTeamNumber(await requestTeamNumber());
    }));

    context.subscriptions.push(vscode.commands.registerCommand('wpilibcore.startTool', async () =>{
        await api.startTool();
    }));

    context.subscriptions.push(vscode.commands.registerCommand('wpilibcore.deployCode', async () =>{
        let workspace = await api.getFirstOrSelectedWorkspace();
        if (workspace === undefined) {
            return;
        }
        await api.deployCode(workspace);
    }));

    context.subscriptions.push(vscode.commands.registerCommand('wpilibcore.debugCode', async () =>{
        let workspace = await api.getFirstOrSelectedWorkspace();
        if (workspace === undefined) {
            return;
        }
        await api.debugCode(workspace);
    }));

    return api;
}
export function activate(context: ExtensionContext) {

	let module = context.asAbsolutePath(path.join('server', 'out', 'server.js'));
	let outputChannel: OutputChannel = Window.createOutputChannel('lsp-multi-server-example');

	function didOpenTextDocument(document: TextDocument): void {
		// We are only interested in language mode text
		if (document.languageId !== 'plaintext' || (document.uri.scheme !== 'file' && document.uri.scheme !== 'untitled')) {
			return;
		}

		let uri = document.uri;
		// Untitled files go to a default client.
		if (uri.scheme === 'untitled' && !defaultClient) {
			let debugOptions = { execArgv: ["--nolazy", "--inspect=6010"] };
			let serverOptions = {
				run: { module, transport: TransportKind.ipc },
				debug: { module, transport: TransportKind.ipc, options: debugOptions}
			};
			let clientOptions: LanguageClientOptions = {
				documentSelector: [
					{ scheme: 'untitled', language: 'plaintext' }
				],
				diagnosticCollectionName: 'lsp-multi-server-example',
				outputChannel: outputChannel
			}
			defaultClient = new LanguageClient('lsp-multi-server-example', 'LSP Multi Server Example', serverOptions, clientOptions);
			defaultClient.start();
			return;
		}
		let folder = Workspace.getWorkspaceFolder(uri);
		// Files outside a folder can't be handled. This might depend on the language.
		// Single file languages like JSON might handle files outside the workspace folders.
		if (!folder) {
			return;
		}
		// If we have nested workspace folders we only start a server on the outer most workspace folder.
		folder = getOuterMostWorkspaceFolder(folder);

		if (!clients.has(folder.uri.toString())) {
			let debugOptions = { execArgv: ["--nolazy", `--inspect=${6011 + clients.size}`] };
			let serverOptions = {
				run: { module, transport: TransportKind.ipc },
				debug: { module, transport: TransportKind.ipc, options: debugOptions}
			};
			let clientOptions: LanguageClientOptions = {
				documentSelector: [
					{ scheme: 'file', language: 'plaintext', pattern: `${folder.uri.fsPath}/**/*` }
				],
				diagnosticCollectionName: 'lsp-multi-server-example',
				workspaceFolder: folder,
				outputChannel: outputChannel
			}
			let client = new LanguageClient('lsp-multi-server-example', 'LSP Multi Server Example', serverOptions, clientOptions);
			client.start();
			clients.set(folder.uri.toString(), client);
		}
	}

	Workspace.onDidOpenTextDocument(didOpenTextDocument);
	Workspace.textDocuments.forEach(didOpenTextDocument);
	Workspace.onDidChangeWorkspaceFolders((event) => {
		for (let folder  of event.removed) {
			let client = clients.get(folder.uri.toString());
			if (client) {
				clients.delete(folder.uri.toString());
				client.stop();
			}
		}
	});
}
	if (_sortedWorkspaceFolders === void 0) {
		_sortedWorkspaceFolders = Workspace.workspaceFolders.map(folder => {
			let result = folder.uri.toString();
			if (result.charAt(result.length - 1) !== '/') {
				result = result + '/';
			}
			return result;
		}).sort(
			(a, b) => {
				return a.length - b.length;
			}
		);
	}
	return _sortedWorkspaceFolders;
}
Workspace.onDidChangeWorkspaceFolders(() => _sortedWorkspaceFolders = undefined);

function getOuterMostWorkspaceFolder(folder: WorkspaceFolder): WorkspaceFolder {
	let sorted = sortedWorkspaceFolders();
	for (let element of sorted) {
		let uri = folder.uri.toString();
		if (uri.charAt(uri.length - 1) !== '/') {
			uri = uri + '/';
		}
		if (uri.startsWith(element)) {
			return Workspace.getWorkspaceFolder(Uri.parse(element));
		}
	}
	return folder;
}
	promptToImportWorkspaceFolders(workspaceFolders);
}

function onDidChangeWorkspaceFolders(event: vscode.WorkspaceFoldersChangeEvent)
{
	let added = event.added.filter((folder) =>
	{
		return isFlashBuilderProject(folder) && !isVSCodeProject(folder);
	});
	if(added.length === 0)
	{
		return;
	}
	checkForFlashBuilderProjectsToImport();
}
vscode.workspace.onDidChangeWorkspaceFolders(onDidChangeWorkspaceFolders);

export function pickFlashBuilderProjectInWorkspace()
{
	let workspaceFolders = vscode.workspace.workspaceFolders
	if(!workspaceFolders)
	{
		vscode.window.showErrorMessage(ERROR_NO_PROJECTS);
		return;
	}

	workspaceFolders = workspaceFolders.filter((folder) =>
	{
		return isFlashBuilderProject(folder);
	});
	if(workspaceFolders.length === 0)
Example #10
0
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,
	};
}
Example #11
0
export function imageDecorator(
    decoratorProvider: (
        document: vscode.TextDocument,
        visibleLines: number[],
        token: vscode.CancellationToken
    ) => Promise<ImageInfoResponse>,
    context: vscode.ExtensionContext,
    client: LanguageClient
) {
    const [major, minor] = vscode.version.split('.').map(v => parseInt(v));

    let scanResults: { [uri: string]: ScanResult } = {};

    let throttleIds = {};
    let throttledScan = (document: vscode.TextDocument, timeout: number = 500) => {
        if (document && document.uri) {
            const lookupKey = document.uri.toString();
            if (throttleIds[lookupKey]) clearTimeout(throttleIds[lookupKey]);
            throttleIds[lookupKey] = setTimeout(() => {
                scan(document);
                delete throttleIds[lookupKey];
            }, timeout);
        }
    };

    const decorate = (
        showImagePreviewOnGutter: boolean,
        editor: vscode.TextEditor,
        imageInfo: ImageInfo,
        lastScanResult: Decoration[]
    ) => {
        let decorations: vscode.DecorationOptions[] = [];

        const normalizedPath = imageInfo.imagePath.startsWith('data:')
            ? imageInfo.imagePath
            : 'file://' + slash(imageInfo.imagePath);
        let uri: vscode.Uri = vscode.Uri.parse(normalizedPath);

        const absoluteImagePath = imageInfo.originalImagePath;
        const underlineEnabled = getConfiguredProperty(
            editor && editor.document ? editor.document : undefined,
            'showUnderline',
            true
        );

        var range = client.protocol2CodeConverter.asRange(imageInfo.range);
        decorations.push({
            range: range,
            hoverMessage: ''
        });

        let decorationRenderOptions: vscode.DecorationRenderOptions = {
            gutterIconPath: uri,
            gutterIconSize: 'contain',
            textDecoration: underlineEnabled ? 'underline' : 'none'
        };
        let textEditorDecorationType: vscode.TextEditorDecorationType = vscode.window.createTextEditorDecorationType(
            decorationRenderOptions
        );
        lastScanResult.push({
            textEditorDecorationType,
            decorations,
            originalImagePath: absoluteImagePath,
            imagePath: imageInfo.imagePath
        });
        const toSingleLineDecorationOption = (source: vscode.DecorationOptions): vscode.DecorationOptions => {
            return {
                hoverMessage: source.hoverMessage,
                range: new vscode.Range(source.range.start, source.range.start),
                renderOptions: source.renderOptions
            };
        };
        if (showImagePreviewOnGutter && editor) {
            editor.setDecorations(textEditorDecorationType, decorations.map(p => toSingleLineDecorationOption(p)));
        }
    };

    let hoverProvider = {
        provideHover(document: vscode.TextDocument, position: vscode.Position): Thenable<vscode.Hover> {
            let maxHeight = getConfiguredProperty(document, 'imagePreviewMaxHeight', 100);
            if (maxHeight < 0) {
                maxHeight = 100;
            }
            let result: Thenable<vscode.Hover> = undefined;

            if (major > 1 || (major == 1 && minor > 7)) {
                const documentDecorators = getDocumentDecorators(document);
                const matchingDecoratorAndItem = documentDecorators.decorations
                    .map(item => {
                        return {
                            item: item,
                            decoration: item.decorations.find(dec => dec.range.contains(position))
                        };
                    })
                    .find(pair => pair.decoration != null);

                if (matchingDecoratorAndItem) {
                    const item = matchingDecoratorAndItem.item;

                    var fallback = (markedString: string) => {
                        const contents = new vscode.MarkdownString(markedString);
                        contents.isTrusted = true;
                        return new vscode.Hover(contents, matchingDecoratorAndItem.decoration.range);
                    };
                    var imageWithSize = (markedString, result) => {
                        markedString += `  \r\n${result.width}x${result.height}`;
                        const contents = new vscode.MarkdownString(markedString);
                        contents.isTrusted = true;
                        return new vscode.Hover(contents, matchingDecoratorAndItem.decoration.range);
                    };
                    let markedString = (imagePath: string, withOpenFileCommand: boolean = true) => {
                        let result = `![${imagePath}](${imagePath}|height=${maxHeight})`;
                        if (
                            withOpenFileCommand &&
                            (item.originalImagePath.indexOf('://') == -1 ||
                                item.originalImagePath.startsWith('file://'))
                        ) {
                            const uri = vscode.Uri.file(item.originalImagePath);
                            const args = [uri];
                            const openFileCommandUrl = vscode.Uri.parse(
                                `command:revealInExplorer?${encodeURIComponent(JSON.stringify(args))}`
                            );
                            result += `  \r\n[Reveal in Side Bar](${openFileCommandUrl} "Reveal in Side Bar")`;
                        }
                        return result;
                    };
                    try {
                        if (item.originalImagePath.startsWith('data:image')) {
                            result = Promise.resolve(fallback(markedString(item.originalImagePath, false)));
                        } else {
                            const sizeOfPromise = util.promisify(sizeOf)(item.imagePath);
                            result = sizeOfPromise.then(
                                result => imageWithSize(markedString(item.imagePath), result),
                                () => fallback(markedString(item.imagePath))
                            );
                        }
                    } catch (error) {
                        result = Promise.resolve(fallback(markedString(item.imagePath)));
                    }
                }
            }
            return result;
        }
    };

    const refreshAllVisibleEditors = () => {
        vscode.window.visibleTextEditors
            .map(p => p.document)
            .filter(p => p != null)
            .forEach(doc => throttledScan(doc));
    };

    const getDocumentDecorators = (document: vscode.TextDocument): ScanResult => {
        const scanResult = scanResults[document.uri.toString()] || {
            decorations: [],
            token: new vscode.CancellationTokenSource()
        };
        scanResults[document.uri.toString()] = scanResult;
        return scanResult;
    };
    const scan = (document: vscode.TextDocument) => {
        const editors = findEditorsForDocument(document);
        if (editors.length > 0) {
            const showImagePreviewOnGutter = getConfiguredProperty(document, 'showImagePreviewOnGutter', true);
            const visibleLines = [];
            for (const editor of editors) {
                for (const range of editor.visibleRanges) {
                    let lineIndex = range.start.line;
                    while (lineIndex <= range.end.line) {
                        visibleLines.push(lineIndex);
                        lineIndex++;
                    }
                }
            }
            const scanResult = getDocumentDecorators(document);
            scanResult.token.cancel();
            scanResult.token = new vscode.CancellationTokenSource();

            decoratorProvider(document, visibleLines, scanResult.token.token)
                .then(symbolResponse => {
                    const scanResult = getDocumentDecorators(document);
                    clearEditorDecorations(document, scanResult.decorations.map(p => p.textEditorDecorationType));
                    scanResult.decorations.length = 0;

                    symbolResponse.images.forEach(p => {
                        editors.forEach(editor =>
                            decorate(showImagePreviewOnGutter, editor, p, scanResult.decorations)
                        );
                    });
                })
                .catch(e => {
                    console.error(e);
                });
        }
    };

    context.subscriptions.push(vscode.languages.registerHoverProvider(['*'], hoverProvider));

    context.subscriptions.push(
        vscode.workspace.onDidChangeTextDocument(e => {
            if (e) {
                throttledScan(e.document);
            }
        })
    );
    context.subscriptions.push(
        vscode.window.onDidChangeActiveTextEditor(e => {
            if (e) {
                throttledScan(e.document);
            }
        })
    );
    context.subscriptions.push(
        vscode.workspace.onDidChangeWorkspaceFolders(() => {
            refreshAllVisibleEditors();
        })
    );
    context.subscriptions.push(
        vscode.window.onDidChangeTextEditorVisibleRanges(event => {
            if (event && event.textEditor && event.textEditor.document) {
                const document = event.textEditor.document;
                throttledScan(document, 50);
            }
        })
    );
    context.subscriptions.push(
        vscode.workspace.onDidOpenTextDocument(e => {
            if (e) {
                throttledScan(e);
            }
        })
    );

    refreshAllVisibleEditors();
}