mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-25 19:18:59 +01:00
Merge remote-tracking branch 'origin/master' into alex/tokenization
This commit is contained in:
@@ -68,7 +68,11 @@
|
||||
{
|
||||
"language": "typescriptreact",
|
||||
"scopeName": "source.tsx",
|
||||
"path": "./syntaxes/TypeScriptReact.tmLanguage.json"
|
||||
"path": "./syntaxes/TypeScriptReact.tmLanguage.json",
|
||||
"embeddedLanguages": {
|
||||
"meta.tag.tsx": "jsx-tags",
|
||||
"meta.tag.without-attributes.tsx": "jsx-tags"
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration": {
|
||||
@@ -99,6 +103,11 @@
|
||||
"default": true,
|
||||
"description": "%typescript.check.tscVersion%"
|
||||
},
|
||||
"typescript.referencesCodeLens.enabled": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "%typescript.referencesCodeLens.enabled%"
|
||||
},
|
||||
"typescript.tsserver.trace": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
|
||||
@@ -24,5 +24,6 @@
|
||||
"format.insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": "Defines space handling after opening and before closing JSX expression braces. Requires TypeScript >= 2.0.6.",
|
||||
"format.placeOpenBraceOnNewLineForFunctions": "Defines whether an open brace is put onto a new line for functions or not.",
|
||||
"format.placeOpenBraceOnNewLineForControlBlocks": "Defines whether an open brace is put onto a new line for control blocks or not.",
|
||||
"javascript.validate.enable": "Enable/disable JavaScript validation."
|
||||
"javascript.validate.enable": "Enable/disable JavaScript validation.",
|
||||
"typescript.referencesCodeLens.enabled": "Enable/disable the references code lens"
|
||||
}
|
||||
144
extensions/typescript/src/features/referencesCodeLensProvider.ts
Normal file
144
extensions/typescript/src/features/referencesCodeLensProvider.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { CodeLensProvider, CodeLens, CancellationToken, TextDocument, Range, Uri, Location, Position, workspace, WorkspaceConfiguration } from 'vscode';
|
||||
import * as Proto from '../protocol';
|
||||
import * as PConst from '../protocol.const';
|
||||
|
||||
import { ITypescriptServiceClient } from '../typescriptService';
|
||||
|
||||
import * as nls from 'vscode-nls';
|
||||
let localize = nls.loadMessageBundle();
|
||||
|
||||
|
||||
class ReferencesCodeLens extends CodeLens {
|
||||
public document: Uri;
|
||||
public file: string;
|
||||
|
||||
constructor(document: Uri, file: string, range: Range) {
|
||||
super(range);
|
||||
this.document = document;
|
||||
this.file = file;
|
||||
}
|
||||
}
|
||||
|
||||
export default class TypeScriptReferencesCodeLensProvider implements CodeLensProvider {
|
||||
private client: ITypescriptServiceClient;
|
||||
private enabled = false;
|
||||
|
||||
constructor(client: ITypescriptServiceClient) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public updateConfiguration(config: WorkspaceConfiguration): void {
|
||||
let typeScriptConfig = workspace.getConfiguration('typescript');
|
||||
this.enabled = typeScriptConfig.get('referencesCodeLens.enabled', false);
|
||||
}
|
||||
|
||||
provideCodeLenses(document: TextDocument, token: CancellationToken): Promise<CodeLens[]> {
|
||||
if (!this.enabled) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
const filepath = this.client.asAbsolutePath(document.uri);
|
||||
if (!filepath) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
return this.client.execute('navtree', { file: filepath }, token).then(response => {
|
||||
const tree = response.body;
|
||||
const referenceableSpans: Range[] = [];
|
||||
if (tree && tree.childItems) {
|
||||
tree.childItems.forEach(item => this.extractReferenceableSymbols(document, item, referenceableSpans));
|
||||
}
|
||||
return Promise.resolve(referenceableSpans.map(span => new ReferencesCodeLens(document.uri, filepath, span)));
|
||||
});
|
||||
}
|
||||
|
||||
resolveCodeLens(inputCodeLens: CodeLens, token: CancellationToken): Promise<CodeLens> {
|
||||
const codeLens = inputCodeLens as ReferencesCodeLens;
|
||||
if (!codeLens.document) {
|
||||
return Promise.reject<CodeLens>(codeLens);
|
||||
}
|
||||
const args: Proto.FileLocationRequestArgs = {
|
||||
file: codeLens.file,
|
||||
line: codeLens.range.start.line + 1,
|
||||
offset: codeLens.range.start.character + 1
|
||||
};
|
||||
return this.client.execute('references', args, token).then(response => {
|
||||
if (response && response.body) {
|
||||
const referenceCount = Math.max(0, response.body.refs.length - 1);
|
||||
const locations = response.body.refs.map(reference =>
|
||||
new Location(Uri.file(reference.file),
|
||||
new Range(
|
||||
new Position(reference.start.line - 1, reference.start.offset - 1),
|
||||
new Position(reference.end.line - 1, reference.end.offset - 1))));
|
||||
|
||||
codeLens.command = {
|
||||
title: referenceCount + ' ' + (referenceCount === 1 ? localize('oneReferenceLabel', 'reference') : localize('manyReferenceLabel', 'references')),
|
||||
command: 'editor.action.showReferences',
|
||||
arguments: [codeLens.document, codeLens.range.start, locations]
|
||||
};
|
||||
return Promise.resolve(codeLens);
|
||||
}
|
||||
return Promise.reject(codeLens);
|
||||
}).catch(() => {
|
||||
codeLens.command = {
|
||||
title: localize('referenceErrorLabel', 'Could not determine references'),
|
||||
command: ''
|
||||
};
|
||||
return Promise.resolve(codeLens);
|
||||
});
|
||||
}
|
||||
|
||||
private extractReferenceableSymbols(document: TextDocument, item: Proto.NavigationTree, results: Range[]) {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
const span = item.spans && item.spans[0];
|
||||
if (span) {
|
||||
const range = new Range(
|
||||
new Position(span.start.line - 1, span.start.offset - 1),
|
||||
new Position(span.end.line - 1, span.end.offset - 1));
|
||||
|
||||
// TODO: TS currently requires the position for 'references 'to be inside of the identifer
|
||||
// Massage the range to make sure this is the case
|
||||
const text = document.getText(range);
|
||||
|
||||
switch (item.kind) {
|
||||
case PConst.Kind.const:
|
||||
case PConst.Kind.let:
|
||||
case PConst.Kind.variable:
|
||||
case PConst.Kind.function:
|
||||
// Only show references for exported variables
|
||||
if (!item.kindModifiers.match(/\bexport\b/)) {
|
||||
break;
|
||||
}
|
||||
// fallthrough
|
||||
|
||||
case PConst.Kind.memberFunction:
|
||||
case PConst.Kind.memberVariable:
|
||||
case PConst.Kind.memberGetAccessor:
|
||||
case PConst.Kind.memberSetAccessor:
|
||||
case PConst.Kind.constructorImplementation:
|
||||
case PConst.Kind.class:
|
||||
case PConst.Kind.interface:
|
||||
case PConst.Kind.type:
|
||||
case PConst.Kind.enum:
|
||||
const identifierMatch = new RegExp(`^(.*?(\\b|\\W))${item.text}`, 'g');
|
||||
const match = identifierMatch.exec(text);
|
||||
const start = match ? match.index + match[1].length : 0;
|
||||
results.push(new Range(
|
||||
new Position(range.start.line, range.start.character + start),
|
||||
new Position(range.start.line, range.start.character + start + item.text.length)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
(item.childItems || []).forEach(item => this.extractReferenceableSymbols(document, item, results));
|
||||
}
|
||||
};
|
||||
@@ -35,6 +35,7 @@ import BufferSyncSupport from './features/bufferSyncSupport';
|
||||
import CompletionItemProvider from './features/completionItemProvider';
|
||||
import WorkspaceSymbolProvider from './features/workspaceSymbolProvider';
|
||||
import CodeActionProvider from './features/codeActionProvider';
|
||||
import ReferenceCodeLensProvider from './features/referencesCodeLensProvider';
|
||||
|
||||
import * as BuildStatus from './utils/buildStatus';
|
||||
import * as ProjectStatus from './utils/projectStatus';
|
||||
@@ -107,6 +108,7 @@ class LanguageProvider {
|
||||
private formattingProvider: FormattingProvider;
|
||||
private formattingProviderRegistration: Disposable | null;
|
||||
private typingsStatus: TypingsStatus;
|
||||
private referenceCodeLensProvider: ReferenceCodeLensProvider;
|
||||
|
||||
private _validate: boolean;
|
||||
|
||||
@@ -156,6 +158,12 @@ class LanguageProvider {
|
||||
this.formattingProviderRegistration = languages.registerDocumentRangeFormattingEditProvider(this.description.modeIds, this.formattingProvider);
|
||||
}
|
||||
|
||||
this.referenceCodeLensProvider = new ReferenceCodeLensProvider(client);
|
||||
this.referenceCodeLensProvider.updateConfiguration(config);
|
||||
if (client.apiVersion.has206Features()) {
|
||||
languages.registerCodeLensProvider(this.description.modeIds, this.referenceCodeLensProvider);
|
||||
}
|
||||
|
||||
this.description.modeIds.forEach(modeId => {
|
||||
let selector: DocumentFilter = { scheme: 'file', language: modeId };
|
||||
languages.registerCompletionItemProvider(selector, this.completionItemProvider, '.');
|
||||
@@ -171,6 +179,7 @@ class LanguageProvider {
|
||||
if (client.apiVersion.has213Features()) {
|
||||
languages.registerCodeActionsProvider(selector, new CodeActionProvider(client, modeId));
|
||||
}
|
||||
|
||||
languages.setLanguageConfiguration(modeId, {
|
||||
indentationRules: {
|
||||
// ^(.*\*/)?\s*\}.*$
|
||||
@@ -217,6 +226,9 @@ class LanguageProvider {
|
||||
if (this.completionItemProvider) {
|
||||
this.completionItemProvider.updateConfiguration(config);
|
||||
}
|
||||
if (this.referenceCodeLensProvider) {
|
||||
this.referenceCodeLensProvider.updateConfiguration(config);
|
||||
}
|
||||
if (this.formattingProvider) {
|
||||
this.formattingProvider.updateConfiguration(config);
|
||||
if (!this.formattingProvider.isEnabled() && this.formattingProviderRegistration) {
|
||||
|
||||
Reference in New Issue
Block a user