Merge branch 'master' into octref/pathCompletion

This commit is contained in:
Pine 2018-03-20 14:25:31 -07:00 committed by GitHub
commit d2b9a7cc45
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
259 changed files with 3386 additions and 1519 deletions

8
.vscode/launch.json vendored
View file

@ -165,12 +165,12 @@
"name": "VS Code Markdown Extension Tests",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceFolder}/extensions/markdown/test-fixtures",
"--extensionDevelopmentPath=${workspaceFolder}/extensions/markdown",
"--extensionTestsPath=${workspaceFolder}/extensions/markdown/out/test"
"${workspaceFolder}/extensions/markdown-language-features/test-fixtures",
"--extensionDevelopmentPath=${workspaceFolder}/extensions/markdown-language-features",
"--extensionTestsPath=${workspaceFolder}/extensions/markdown-language-features/out/test"
],
"outFiles": [
"${workspaceFolder}/extensions/markdown/out/**/*.js"
"${workspaceFolder}/extensions/markdown-language-features/out/**/*.js"
]
},
{

View file

@ -1,6 +1,5 @@
{
"editor.insertSpaces": false,
"files.eol": "\n",
"files.trimTrailingWhitespace": true,
"files.exclude": {
".git": true,

View file

@ -1,12 +1,12 @@
[
{
"name": "ms-vscode.node-debug",
"version": "1.22.5",
"version": "1.22.7",
"repo": "https://github.com/Microsoft/vscode-node-debug"
},
{
"name": "ms-vscode.node-debug2",
"version": "1.22.2",
"version": "1.22.3",
"repo": "https://github.com/Microsoft/vscode-node-debug2"
}
]

View file

@ -82,7 +82,7 @@ const indentationFilter = [
'!build/**/*.sh',
'!build/tfs/**/*.js',
'!**/Dockerfile',
'!extensions/markdown/media/*.js'
'!extensions/markdown-language-features/media/*.js'
];
const copyrightFilter = [
@ -104,7 +104,7 @@ const copyrightFilter = [
'!build/**/*.init',
'!resources/linux/snap/snapcraft.yaml',
'!resources/win32/bin/code.js',
'!extensions/markdown/media/tomorrow.css',
'!extensions/markdown-language-features/media/tomorrow.css',
'!extensions/html-language-features/server/src/modes/typescript/*'
];

View file

@ -10,7 +10,7 @@ import { getCSSLanguageService, getSCSSLanguageService } from 'vscode-css-langua
import { TextDocument, CompletionList } from 'vscode-languageserver-types';
import { getEmmetCompletionParticipants } from 'vscode-emmet-helper';
suite('Emmet Support', () => {
suite('CSS Emmet Support', () => {
const cssLanguageService = getCSSLanguageService();
const scssLanguageService = getSCSSLanguageService();
@ -44,6 +44,8 @@ suite('Emmet Support', () => {
}
test('Css Emmet Completions', function (): any {
this.skip(); // disabled again (see #29113)
assertCompletions('css', '.foo { display: none; m10| }', 'margin: 10px;', 'margin: 10px;');
assertCompletions('css', 'foo { display: none; pos:f| }', 'position: fixed;', 'position: fixed;');
assertCompletions('css', 'foo { display: none; margin: a| }', null, null);
@ -55,6 +57,8 @@ suite('Emmet Support', () => {
});
test('Scss Emmet Completions', function (): any {
this.skip(); // disabled again (see #29113)
assertCompletions('scss', '.foo { display: none; .bar { m10| } }', 'margin: 10px;', 'margin: 10px;');
assertCompletions('scss', 'foo { display: none; .bar { pos:f| } }', 'position: fixed;', 'position: fixed;');
assertCompletions('scss', 'foo { display: none; margin: a| .bar {}}', null, null);
@ -64,5 +68,4 @@ suite('Emmet Support', () => {
assertCompletions('scss', 'foo { display: none|; }', null, null);
assertCompletions('scss', '.foo { display: none; -m-m10| }', 'margin: 10px;', '-moz-margin: 10px;\nmargin: 10px;');
});
});

View file

@ -6,37 +6,55 @@
'use strict';
import { Model } from './model';
import { Uri } from 'vscode';
import { Repository as ModelRepository } from './repository';
import { Uri, SourceControlInputBox } from 'vscode';
export interface InputBox {
value: string;
}
export class InputBoxImpl implements InputBox {
set value(value: string) { this.inputBox.value = value; }
get value(): string { return this.inputBox.value; }
constructor(private inputBox: SourceControlInputBox) { }
}
export interface Repository {
readonly rootUri: Uri;
readonly inputBox: InputBox;
}
export interface API {
getRepositories(): Promise<Repository[]>;
export class RepositoryImpl implements Repository {
readonly rootUri: Uri;
readonly inputBox: InputBox;
constructor(repository: ModelRepository) {
this.rootUri = Uri.file(repository.root);
this.inputBox = new InputBoxImpl(repository.inputBox);
}
}
export function createApi(modelPromise: Promise<Model>) {
return {
async getRepositories(): Promise<Repository[]> {
const model = await modelPromise;
export interface API {
getRepositories(): Promise<Repository[]>;
getGitPath(): Promise<string>;
}
return model.repositories.map(repository => ({
rootUri: Uri.file(repository.root),
inputBox: {
set value(value: string) {
repository.inputBox.value = value;
},
get value(): string {
return repository.inputBox.value;
}
}
}));
}
};
export class APIImpl implements API {
constructor(private modelPromise: Promise<Model>) { }
async getGitPath(): Promise<string> {
const model = await this.modelPromise;
return model.git.path;
}
async getRepositories(): Promise<Repository[]> {
const model = await this.modelPromise;
return model.repositories.map(repository => new RepositoryImpl(repository));
}
}
export function createApi(modelPromise: Promise<Model>): API {
return new APIImpl(modelPromise);
}

View file

@ -366,14 +366,14 @@ function getGitErrorCode(stderr: string): string | undefined {
export class Git {
private gitPath: string;
readonly path: string;
private env: any;
private _onOutput = new EventEmitter();
get onOutput(): EventEmitter { return this._onOutput; }
constructor(options: IGitOptions) {
this.gitPath = options.gitPath;
this.path = options.gitPath;
this.env = options.env || {};
}
@ -447,7 +447,7 @@ export class Git {
}
spawn(args: string[], options: SpawnOptions = {}): cp.ChildProcess {
if (!this.gitPath) {
if (!this.path) {
throw new Error('git could not be found in the system.');
}
@ -469,7 +469,7 @@ export class Git {
this.log(`> git ${args.join(' ')}\n`);
}
return cp.spawn(this.gitPath, args, options);
return cp.spawn(this.path, args, options);
}
private log(output: string): void {

View file

@ -66,7 +66,7 @@ export class Model {
private disposables: Disposable[] = [];
constructor(private git: Git, private globalState: Memento, private outputChannel: OutputChannel) {
constructor(readonly git: Git, private globalState: Memento, private outputChannel: OutputChannel) {
workspace.onDidChangeWorkspaceFolders(this.onDidChangeWorkspaceFolders, this, this.disposables);
this.onDidChangeWorkspaceFolders({ added: workspace.workspaceFolders || [], removed: [] });

View file

@ -8,7 +8,7 @@ import * as path from 'path';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { languages, ExtensionContext, IndentAction, Position, TextDocument, Range, CompletionItem, CompletionItemKind, SnippetString, FoldingRangeList, FoldingRange, workspace, FoldingContext } from 'vscode';
import { languages, ExtensionContext, IndentAction, Position, TextDocument, Range, CompletionItem, CompletionItemKind, SnippetString, FoldingRangeList, FoldingRange, FoldingContext } from 'vscode';
import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, RequestType, TextDocumentPositionParams, Disposable, CancellationToken } from 'vscode-languageclient';
import { EMPTY_ELEMENTS } from './htmlEmptyTagsShared';
import { activateTagClosing } from './tagClosing';
@ -28,8 +28,6 @@ interface IPackageInfo {
let telemetryReporter: TelemetryReporter | null;
let foldingProviderRegistration: Disposable | undefined = void 0;
const foldingSetting = 'html.experimental.syntaxFolding';
export function activate(context: ExtensionContext) {
let toDispose = context.subscriptions;
@ -83,14 +81,7 @@ export function activate(context: ExtensionContext) {
}
});
toDispose.push(disposable);
initFoldingProvider();
toDispose.push(workspace.onDidChangeConfiguration(c => {
if (c.affectsConfiguration(foldingSetting)) {
initFoldingProvider();
}
}));
toDispose.push({ dispose: () => foldingProviderRegistration && foldingProviderRegistration.dispose() });
toDispose.push(initFoldingProvider());
});
languages.setLanguageConfiguration('html', {
@ -167,34 +158,24 @@ export function activate(context: ExtensionContext) {
}
});
function initFoldingProvider() {
let enable = workspace.getConfiguration().get(foldingSetting);
if (enable) {
if (!foldingProviderRegistration) {
foldingProviderRegistration = languages.registerFoldingProvider(documentSelector, {
provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken) {
const param: FoldingRangeRequestParam = {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
maxRanges: context.maxRanges
};
return client.sendRequest(FoldingRangesRequest.type, param, token).then(res => {
if (res && Array.isArray(res.ranges)) {
return new FoldingRangeList(res.ranges.map(r => new FoldingRange(r.startLine, r.endLine, r.type)));
}
return null;
}, error => {
client.logFailedRequest(FoldingRangesRequest.type, error);
return null;
});
function initFoldingProvider(): Disposable {
return languages.registerFoldingProvider(documentSelector, {
provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken) {
const param: FoldingRangeRequestParam = {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
maxRanges: context.maxRanges
};
return client.sendRequest(FoldingRangesRequest.type, param, token).then(res => {
if (res && Array.isArray(res.ranges)) {
return new FoldingRangeList(res.ranges.map(r => new FoldingRange(r.startLine, r.endLine, r.type)));
}
return null;
}, error => {
client.logFailedRequest(FoldingRangesRequest.type, error);
return null;
});
}
} else {
if (foldingProviderRegistration) {
foldingProviderRegistration.dispose();
foldingProviderRegistration = void 0;
}
}
});
}
}

View file

@ -154,11 +154,6 @@
"default": true,
"description": "%html.autoClosingTags%"
},
"html.experimental.syntaxFolding": {
"type": "boolean",
"default": false,
"description": "%html.experimental.syntaxFolding%"
},
"html.trace.server": {
"type": "string",
"scope": "window",

View file

@ -22,6 +22,5 @@
"html.trace.server.desc": "Traces the communication between VS Code and the HTML language server.",
"html.validate.scripts": "Configures if the built-in HTML language support validates embedded scripts.",
"html.validate.styles": "Configures if the built-in HTML language support validates embedded styles.",
"html.experimental.syntaxFolding": "Enables/disables syntax aware folding markers.",
"html.autoClosingTags": "Enable/disable autoclosing of HTML tags."
}

View file

@ -21,8 +21,8 @@
"@types/node": "7.0.43"
},
"scripts": {
"compile": "gulp compile-extension:html-server",
"watch": "gulp watch-extension:html-server",
"compile": "gulp compile-extension:html-language-features-server",
"watch": "gulp watch-extension:html-language-features-server",
"install-service-next": "yarn add vscode-css-languageservice@next && yarn add vscode-html-languageservice@next",
"install-service-local": "npm install ../../../../vscode-css-languageservice -f && npm install ../../../../vscode-html-languageservice -f",
"install-server-next": "yarn add vscode-languageserver@next",

View file

@ -292,9 +292,9 @@ export function getJavascriptMode(documentRegions: LanguageModelCache<HTMLDocume
let endLine = curr.end.line;
if (startLine < endLine && startLine >= rangeStartLine && endLine < rangeEndLine) {
let foldingRange: FoldingRange = { startLine, endLine };
let match = document.getText(curr).match(/^\s*\/(\/\s*#(?:end)?region\b)|([\*\/])/);
let match = document.getText(curr).match(/^\s*\/(?:(\/\s*#(?:end)?region\b)|(\*|\/))/);
if (match) {
foldingRange.type = match[1].length ? FoldingRangeType.Region : FoldingRangeType.Comment;
foldingRange.type = match[1] ? FoldingRangeType.Region : FoldingRangeType.Comment;
}
ranges.push(foldingRange);
}

View file

@ -22,7 +22,7 @@ export interface ItemDescription {
}
suite('Completions', () => {
suite('HTML Completions', () => {
let assertCompletion = function (completions: CompletionList, expected: ItemDescription, document: TextDocument, offset: number) {
let matches = completions.items.filter(completion => {

View file

@ -7,7 +7,7 @@
import * as assert from 'assert';
import { getDocumentContext } from '../utils/documentContext';
suite('Document Context', () => {
suite('HTML Document Context', () => {
test('Context', function (): any {
const docURI = 'file:///users/test/folder/test.html';

View file

@ -15,7 +15,7 @@ import * as embeddedSupport from '../modes/embeddedSupport';
import { getEmmetCompletionParticipants } from 'vscode-emmet-helper';
import { getCSSMode } from '../modes/cssMode';
suite('Emmet Support', () => {
suite('HTML Emmet Support', () => {
const htmlLanguageService = getLanguageService();

View file

@ -34,7 +34,7 @@ function r(startLine: number, endLine: number, type?: string): ExpectedIndentRan
return { startLine, endLine, type };
}
suite('Object Folding', () => {
suite('HTML Folding', () => {
test('Fold one level', () => {
let input = [
/*0*/'<html>',
@ -130,7 +130,7 @@ suite('Object Folding', () => {
/* 6*/' };',
/* 7*/'</script>',
/* 8*/'<script>',
/* 9*/' test(() => {',
/* 9*/' test(() => { // hello',
/*10*/' f();',
/*11*/' });',
/*12*/'</script>',
@ -206,7 +206,7 @@ suite('Object Folding', () => {
/*2*/'</div>',
];
assertRanges(input, [r(0, 1)]);
});
});
test('Fold intersecting region', () => {
let input = [
@ -218,7 +218,7 @@ suite('Object Folding', () => {
/*5*/'<!-- #endregion -->',
];
assertRanges(input, [r(0, 3)]);
});
});
test('Test limit', () => {

View file

@ -7,7 +7,7 @@
import * as assert from 'assert';
import * as words from '../utils/strings';
suite('Words', () => {
suite('HTML Words', () => {
let wordRegex = /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g;

View file

@ -62,7 +62,8 @@
"tokenTypes": {
"entity.name.type.instance.jsdoc": "other",
"entity.name.function.tagged-template.js": "other",
"entity.name.function.tagged-template.js.jsx": "other"
"entity.name.function.tagged-template.js.jsx": "other",
"meta.import string.quoted": "other"
}
},
{
@ -78,7 +79,8 @@
"tokenTypes": {
"entity.name.type.instance.jsdoc": "other",
"entity.name.function.tagged-template.js": "other",
"entity.name.function.tagged-template.js.jsx": "other"
"entity.name.function.tagged-template.js.jsx": "other",
"meta.import string.quoted": "other"
}
},
{

View file

@ -57,9 +57,6 @@ interface JSONSchemaSettings {
let telemetryReporter: TelemetryReporter | undefined;
let foldingProviderRegistration: Disposable | undefined = void 0;
const foldingSetting = 'json.experimental.syntaxFolding';
export function activate(context: ExtensionContext) {
let toDispose = context.subscriptions;
@ -130,13 +127,7 @@ export function activate(context: ExtensionContext) {
client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociation(context));
initFoldingProvider();
toDispose.push(workspace.onDidChangeConfiguration(c => {
if (c.affectsConfiguration(foldingSetting)) {
initFoldingProvider();
}
}));
toDispose.push({ dispose: () => foldingProviderRegistration && foldingProviderRegistration.dispose() });
toDispose.push(initFoldingProvider());
});
let languageConfiguration: LanguageConfiguration = {
@ -149,34 +140,24 @@ export function activate(context: ExtensionContext) {
languages.setLanguageConfiguration('json', languageConfiguration);
languages.setLanguageConfiguration('jsonc', languageConfiguration);
function initFoldingProvider() {
let enable = workspace.getConfiguration().get(foldingSetting);
if (enable) {
if (!foldingProviderRegistration) {
foldingProviderRegistration = languages.registerFoldingProvider(documentSelector, {
provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken) {
const param: FoldingRangeRequestParam = {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
maxRanges: context.maxRanges
};
return client.sendRequest(FoldingRangesRequest.type, param, token).then(res => {
if (res && Array.isArray(res.ranges)) {
return new FoldingRangeList(res.ranges.map(r => new FoldingRange(r.startLine, r.endLine, r.type)));
}
return null;
}, error => {
client.logFailedRequest(FoldingRangesRequest.type, error);
return null;
});
function initFoldingProvider(): Disposable {
return languages.registerFoldingProvider(documentSelector, {
provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken) {
const param: FoldingRangeRequestParam = {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
maxRanges: context.maxRanges
};
return client.sendRequest(FoldingRangesRequest.type, param, token).then(res => {
if (res && Array.isArray(res.ranges)) {
return new FoldingRangeList(res.ranges.map(r => new FoldingRange(r.startLine, r.endLine, r.type)));
}
return null;
}, error => {
client.logFailedRequest(FoldingRangesRequest.type, error);
return null;
});
}
} else {
if (foldingProviderRegistration) {
foldingProviderRegistration.dispose();
foldingProviderRegistration = void 0;
}
}
});
}
}

View file

@ -85,11 +85,6 @@
"default": true,
"description": "%json.colorDecorators.enable.desc%",
"deprecationMessage": "%json.colorDecorators.enable.deprecationMessage%"
},
"json.experimental.syntaxFolding": {
"type": "boolean",
"default": false,
"description": "%json.experimental.syntaxFolding%"
}
}
},

View file

@ -9,6 +9,5 @@
"json.format.enable.desc": "Enable/disable default JSON formatter (requires restart)",
"json.tracing.desc": "Traces the communication between VS Code and the JSON language server.",
"json.colorDecorators.enable.desc": "Enables or disables color decorators",
"json.colorDecorators.enable.deprecationMessage": "The setting `json.colorDecorators.enable` has been deprecated in favor of `editor.colorDecorators`.",
"json.experimental.syntaxFolding": "Enables/disables syntax aware folding markers."
"json.colorDecorators.enable.deprecationMessage": "The setting `json.colorDecorators.enable` has been deprecated in favor of `editor.colorDecorators`."
}

View file

@ -20,8 +20,8 @@
"@types/mocha": "2.2.33"
},
"scripts": {
"compile": "gulp compile-extension:json-server",
"watch": "gulp watch-extension:json-server",
"compile": "gulp compile-extension:json-language-features-server",
"watch": "gulp watch-extension:json-language-features-server",
"install-service-next": "yarn add vscode-json-languageservice@next",
"install-service-local": "yarn link vscode-json-languageservice",
"install-server-next": "yarn add vscode-languageserver@next",

View file

@ -32,7 +32,7 @@ function r(startLine: number, endLine: number, type?: string): ExpectedIndentRan
return { startLine, endLine, type };
}
suite('Object Folding', () => {
suite('JSON Folding', () => {
test('Fold one level', () => {
let input = [
/*0*/'{',

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 857 B

After

Width:  |  Height:  |  Size: 857 B

View file

Before

Width:  |  Height:  |  Size: 819 B

After

Width:  |  Height:  |  Size: 819 B

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 417 B

After

Width:  |  Height:  |  Size: 417 B

View file

Before

Width:  |  Height:  |  Size: 262 B

After

Width:  |  Height:  |  Size: 262 B

View file

@ -529,26 +529,26 @@ module.exports = throttle;
/*! no static exports found */
/***/ (function(module, exports) {
var g;
// This works in non-strict mode
g = (function() {
return this;
})();
try {
// This works if eval is allowed (see CSP)
g = g || Function("return this")() || (1, eval)("this");
} catch (e) {
// This works if the window reference is available
if (typeof window === "object") g = window;
}
// g can still be undefined, but nothing to do about it...
// We return undefined, instead of nothing here, so it's
// easier to handle this case. if(!global) { ...}
module.exports = g;
var g;
// This works in non-strict mode
g = (function() {
return this;
})();
try {
// This works if eval is allowed (see CSP)
g = g || Function("return this")() || (1, eval)("this");
} catch (e) {
// This works if the window reference is available
if (typeof window === "object") g = window;
}
// g can still be undefined, but nothing to do about it...
// We return undefined, instead of nothing here, so it's
// easier to handle this case. if(!global) { ...}
module.exports = g;
/***/ }),

View file

@ -277,10 +277,10 @@
]
},
"scripts": {
"compile": "gulp compile-extension:markdown && npm run build-preview",
"watch": "npm run build-preview && gulp watch-extension:markdown",
"compile": "gulp compile-extension:markdown-language-features && npm run build-preview",
"watch": "npm run build-preview && gulp watch-extension:markdown-language-features",
"vscode:prepublish": "npm run build-ext && npm run build-preview",
"build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:markdown ./tsconfig.json",
"build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:markdown-language-features ./tsconfig.json",
"build-preview": "webpack --mode development"
},
"dependencies": {

View file

@ -48,6 +48,7 @@ export class MarkdownPreview {
previewColumn, {
enableScripts: true,
enableCommandUris: true,
enableFindWidget: true,
localResourceRoots: this.getLocalResourceRoots(_resource)
});

View file

@ -3,7 +3,7 @@
"version": "0.0.1",
"description": "Dependencies shared by all extensions",
"dependencies": {
"typescript": "2.7.2"
"typescript": "2.8.0-insiders.20180320"
},
"scripts": {
"postinstall": "node ./postinstall"

View file

@ -10,6 +10,7 @@
"editorSuggestWidget.background": "#F3F3F3",
"activityBarBadge.background": "#007ACC",
"sideBarTitle.foreground": "#6F6F6F",
"list.hoverBackground": "#E8E8E8"
"list.hoverBackground": "#E8E8E8",
"input.placeholderForeground": "#ADADAD"
}
}

View file

@ -46,7 +46,8 @@
"tokenTypes": {
"entity.name.type.instance.jsdoc": "other",
"entity.name.function.tagged-template.ts": "other",
"entity.name.function.tagged-template.tsx": "other"
"entity.name.function.tagged-template.tsx": "other",
"meta.import string.quoted": "other"
}
},
{
@ -62,7 +63,8 @@
"tokenTypes": {
"entity.name.type.instance.jsdoc": "other",
"entity.name.function.tagged-template.ts": "other",
"entity.name.function.tagged-template.tsx": "other"
"entity.name.function.tagged-template.tsx": "other",
"meta.import string.quoted": "other"
}
}
],

View file

@ -36,6 +36,7 @@
"onCommand:javascript.goToProjectConfig",
"onCommand:typescript.goToProjectConfig",
"onCommand:typescript.openTsServerLog",
"onCommand:typescript.organizeImports",
"onCommand:workbench.action.tasks.runTask"
],
"main": "./out/extension",
@ -460,6 +461,18 @@
"value": "%typescript.restartTsServer%"
},
"category": "TypeScript"
},
{
"command": "typescript.organizeImports",
"title": "%typescript.organizeImports%",
"category": "TypeScript"
}
],
"keybindings": [
{
"command": "typescript.organizeImports",
"key": "shift+alt+o",
"when": "typescript.isManagedFile && typescript.canOrganizeImports"
}
],
"menus": {
@ -507,6 +520,10 @@
{
"command": "typescript.restartTsServer",
"when": "typescript.isManagedFile"
},
{
"command": "typescript.organizeImports",
"when": "typescript.isManagedFile && typescript.canOrganizeImports"
}
]
},

View file

@ -50,5 +50,6 @@
"javascript.implicitProjectConfig.experimentalDecorators": "Enable/disable 'experimentalDecorators' for JavaScript files that are not part of a project. Existing jsconfig.json or tsconfig.json files override this setting. Requires TypeScript >=2.3.1.",
"typescript.autoImportSuggestions.enabled": "Enable/disable auto import suggestions. Requires TypeScript >=2.6.1",
"typescript.experimental.syntaxFolding": "Enables/disables syntax aware folding markers.",
"taskDefinition.tsconfig.description": "The tsconfig file that defines the TS build."
"taskDefinition.tsconfig.description": "The tsconfig file that defines the TS build.",
"typescript.organizeImports": "Organize Imports"
}

View file

@ -19,6 +19,7 @@ import ManagedFileContextManager from './utils/managedFileContext';
import { lazy, Lazy } from './utils/lazy';
import * as fileSchemes from './utils/fileSchemes';
import LogDirectoryProvider from './utils/logDirectoryProvider';
import { OrganizeImportsCommand, OrganizeImportsContextManager } from './features/organizeImports';
export function activate(
context: vscode.ExtensionContext
@ -70,7 +71,14 @@ function createLazyClientHost(
plugins,
commandManager,
logDirectoryProvider);
context.subscriptions.push(clientHost);
const organizeImportsContext = new OrganizeImportsContextManager();
clientHost.serviceClient.onTsServerStarted(api => {
organizeImportsContext.onDidChangeApiVersion(api);
}, null, context.subscriptions);
clientHost.serviceClient.onReady(() => {
context.subscriptions.push(
ProjectStatus.create(
@ -79,6 +87,7 @@ function createLazyClientHost(
path => new Promise<boolean>(resolve => setTimeout(() => resolve(clientHost.handles(path)), 750)),
context.workspaceState));
});
return clientHost;
});
}
@ -94,6 +103,7 @@ function registerCommands(
commandManager.register(new commands.RestartTsServerCommand(lazyClientHost));
commandManager.register(new commands.TypeScriptGoToProjectConfigCommand(lazyClientHost));
commandManager.register(new commands.JavaScriptGoToProjectConfigCommand(lazyClientHost));
commandManager.register(new OrganizeImportsCommand(lazyClientHost));
}
function isSupportedDocument(

View file

@ -7,7 +7,7 @@ import { CodeLensProvider, CodeLens, CancellationToken, TextDocument, Range, Uri
import * as Proto from '../protocol';
import { ITypeScriptServiceClient } from '../typescriptService';
import { tsTextSpanToVsRange } from '../utils/convert';
import * as typeConverters from '../utils/typeConverters';
import { escapeRegExp } from '../utils/regexp';
export class ReferencesCodeLens extends CodeLens {
@ -136,7 +136,7 @@ export abstract class TypeScriptBaseCodeLensProvider implements CodeLensProvider
return null;
}
const range = tsTextSpanToVsRange(span);
const range = typeConverters.Range.fromTextSpan(span);
const text = document.getText(range);
const identifierMatch = new RegExp(`^(.*?(\\b|\\W))${escapeRegExp(item.text || '')}(\\b|\\W)`, 'gm');

View file

@ -153,7 +153,7 @@ export default class BufferSyncSupport {
private readonly disposables: Disposable[] = [];
private readonly syncedBuffers: SyncedBufferMap;
private pendingDiagnostics = new Map<string, number>();
private readonly pendingDiagnostics = new Map<string, number>();
private readonly diagnosticDelayer: Delayer<any>;
constructor(
@ -271,16 +271,9 @@ export default class BufferSyncSupport {
if (!this._validate) {
return;
}
let files = Array.from(this.pendingDiagnostics.entries()).map(([key, value]) => {
return {
file: key,
time: value
};
}).sort((a, b) => {
return a.time - b.time;
}).map((value) => {
return value.file;
});
const files = Array.from(this.pendingDiagnostics.entries())
.sort((a, b) => a[1] - b[1])
.map(entry => entry[0]);
// Add all open TS buffers to the geterr request. They might be visible
for (const file of this.syncedBuffers.allResources) {

View file

@ -11,11 +11,10 @@ import TypingsStatus from '../utils/typingsStatus';
import * as Proto from '../protocol';
import * as PConst from '../protocol.const';
import * as Previewer from '../utils/previewer';
import { tsTextSpanToVsRange, vsPositionToTsFileLocation } from '../utils/convert';
import * as typeConverters from '../utils/typeConverters';
import * as nls from 'vscode-nls';
import { applyCodeAction } from '../utils/codeAction';
import * as languageModeIds from '../utils/languageModeIds';
import { CommandManager, Command } from '../utils/commandManager';
const localize = nls.loadMessageBundle();
@ -51,14 +50,14 @@ class MyCompletionItem extends vscode.CompletionItem {
this.useCodeSnippet = useCodeSnippetsOnMethodSuggest && (this.kind === vscode.CompletionItemKind.Function || this.kind === vscode.CompletionItemKind.Method);
if (tsEntry.replacementSpan) {
this.range = tsTextSpanToVsRange(tsEntry.replacementSpan);
this.range = typeConverters.Range.fromTextSpan(tsEntry.replacementSpan);
}
if (tsEntry.insertText) {
this.insertText = tsEntry.insertText;
if (tsEntry.replacementSpan) {
this.range = tsTextSpanToVsRange(tsEntry.replacementSpan);
this.range = typeConverters.Range.fromTextSpan(tsEntry.replacementSpan);
if (this.insertText[0] === '[') { // o.x -> o['x']
this.filterText = '.' + this.label;
}
@ -281,7 +280,7 @@ export default class TypeScriptCompletionItemProvider implements vscode.Completi
}
const args: Proto.CompletionsRequestArgs = {
...vsPositionToTsFileLocation(file, position),
...typeConverters.Position.toFileLocationRequestArgs(file, position),
includeExternalModuleExports: completionConfiguration.autoImportSuggestions,
includeInsertTextCompletions: true
};
@ -330,7 +329,7 @@ export default class TypeScriptCompletionItemProvider implements vscode.Completi
item.resolve();
const args: Proto.CompletionDetailsRequestArgs = {
...vsPositionToTsFileLocation(filepath, item.position),
...typeConverters.Position.toFileLocationRequestArgs(filepath, item.position),
entryNames: [
item.tsEntry.source ? { name: item.tsEntry.name, source: item.tsEntry.source } : item.tsEntry.name
]
@ -351,34 +350,74 @@ export default class TypeScriptCompletionItemProvider implements vscode.Completi
item.detail = detail.displayParts.length ? Previewer.plain(detail.displayParts) : undefined;
item.documentation = this.getDocumentation(detail, item);
if (detail.codeActions && detail.codeActions.length) {
item.command = {
title: '',
command: ApplyCompletionCodeActionCommand.ID,
arguments: [filepath, detail.codeActions]
};
}
const { command, additionalTextEdits } = this.getCodeActions(detail, filepath);
item.command = command;
item.additionalTextEdits = additionalTextEdits;
if (detail && item.useCodeSnippet) {
const shouldCompleteFunction = await this.isValidFunctionCompletionContext(filepath, item.position);
if (shouldCompleteFunction) {
item.insertText = this.snippetForFunctionCall(item, detail);
}
return item;
}
return item;
}
private getCodeActions(
detail: Proto.CompletionEntryDetails,
filepath: string
): { command?: vscode.Command, additionalTextEdits?: vscode.TextEdit[] } {
if (!detail.codeActions || !detail.codeActions.length) {
return {};
}
// Try to extract out the additionalTextEdits for the current file.
// Also check if we still have to apply other workspace edits and commands
// using a vscode command
const additionalTextEdits: vscode.TextEdit[] = [];
let hasReaminingCommandsOrEdits = false;
for (const tsAction of detail.codeActions) {
if (tsAction.commands) {
hasReaminingCommandsOrEdits = true;
}
// Apply all edits in the current file using `additionalTextEdits`
if (tsAction.changes) {
for (const change of tsAction.changes) {
if (change.fileName === filepath) {
additionalTextEdits.push(...change.textChanges.map(typeConverters.TextEdit.fromCodeEdit));
} else {
hasReaminingCommandsOrEdits = true;
}
}
}
}
let command: vscode.Command | undefined = undefined;
if (hasReaminingCommandsOrEdits) {
// Create command that applies all edits not in the current file.
command = {
title: '',
command: ApplyCompletionCodeActionCommand.ID,
arguments: [filepath, detail.codeActions.map((x): Proto.CodeAction => ({
commands: x.commands,
description: x.description,
changes: x.changes.filter(x => x.fileName !== filepath)
}))]
};
}
return {
command,
additionalTextEdits: additionalTextEdits.length ? additionalTextEdits : undefined
};
}
private shouldEnableDotCompletions(
document: vscode.TextDocument,
position: vscode.Position
): boolean {
// Only enable dot completions in TS files for now
if (document.languageId !== languageModeIds.typescript && document.languageId === languageModeIds.typescriptreact) {
return false;
}
// TODO: Workaround for https://github.com/Microsoft/TypeScript/issues/13456
// Only enable dot completions when previous character is an identifier.
// Prevents incorrectly completing while typing spread operators.
@ -455,7 +494,7 @@ export default class TypeScriptCompletionItemProvider implements vscode.Completi
// Workaround for https://github.com/Microsoft/TypeScript/issues/12677
// Don't complete function calls inside of destructive assigments or imports
try {
const infoResponse = await this.client.execute('quickinfo', vsPositionToTsFileLocation(filepath, position));
const infoResponse = await this.client.execute('quickinfo', typeConverters.Position.toFileLocationRequestArgs(filepath, position));
const info = infoResponse.body;
switch (info && info.kind) {
case 'var':

View file

@ -7,11 +7,11 @@ import { TextDocument, Position, CancellationToken, Location } from 'vscode';
import * as Proto from '../protocol';
import { ITypeScriptServiceClient } from '../typescriptService';
import { tsTextSpanToVsRange, vsPositionToTsFileLocation } from '../utils/convert';
import * as typeConverters from '../utils/typeConverters';
export default class TypeScriptDefinitionProviderBase {
constructor(
private client: ITypeScriptServiceClient
private readonly client: ITypeScriptServiceClient
) { }
protected async getSymbolLocations(
@ -25,19 +25,12 @@ export default class TypeScriptDefinitionProviderBase {
return undefined;
}
const args = vsPositionToTsFileLocation(filepath, position);
const args = typeConverters.Position.toFileLocationRequestArgs(filepath, position);
try {
const response = await this.client.execute(definitionType, args, token);
const locations: Proto.FileSpan[] = (response && response.body) || [];
if (!locations || locations.length === 0) {
return [];
}
return locations.map(location => {
const resource = this.client.asUrl(location.file);
return resource
? new Location(resource, tsTextSpanToVsRange(location))
: undefined;
}).filter(x => x) as Location[];
return locations.map(location =>
typeConverters.Location.fromTextSpan(this.client.asUrl(location.file), location));
} catch {
return [];
}

View file

@ -30,18 +30,27 @@ class DiagnosticSet {
}
}
export default class DiagnosticsManager {
export enum DiagnosticKind {
Syntax,
Semantic,
Suggestion
}
private readonly syntaxDiagnostics: DiagnosticSet;
private readonly semanticDiagnostics: DiagnosticSet;
const allDiagnosticKinds = [DiagnosticKind.Syntax, DiagnosticKind.Semantic, DiagnosticKind.Suggestion];
export class DiagnosticsManager {
private readonly diagnostics = new Map<DiagnosticKind, DiagnosticSet>();
private readonly currentDiagnostics: DiagnosticCollection;
private _validate: boolean = true;
constructor(
language: string
) {
this.syntaxDiagnostics = new DiagnosticSet();
this.semanticDiagnostics = new DiagnosticSet();
for (const kind of allDiagnosticKinds) {
this.diagnostics.set(kind, new DiagnosticSet());
}
this.currentDiagnostics = languages.createDiagnosticCollection(language);
}
@ -51,8 +60,10 @@ export default class DiagnosticsManager {
public reInitialize(): void {
this.currentDiagnostics.clear();
this.syntaxDiagnostics.clear();
this.semanticDiagnostics.clear();
for (const diagnosticSet of this.diagnostics.values()) {
diagnosticSet.clear();
}
}
public set validate(value: boolean) {
@ -65,14 +76,16 @@ export default class DiagnosticsManager {
}
}
public syntaxDiagnosticsReceived(file: Uri, syntaxDiagnostics: Diagnostic[]): void {
this.syntaxDiagnostics.set(file, syntaxDiagnostics);
this.updateCurrentDiagnostics(file);
}
public semanticDiagnosticsReceived(file: Uri, semanticDiagnostics: Diagnostic[]): void {
this.semanticDiagnostics.set(file, semanticDiagnostics);
this.updateCurrentDiagnostics(file);
public diagnosticsReceived(
kind: DiagnosticKind,
file: Uri,
syntaxDiagnostics: Diagnostic[]
): void {
const diagnostics = this.diagnostics.get(kind);
if (diagnostics) {
diagnostics.set(file, syntaxDiagnostics);
this.updateCurrentDiagnostics(file);
}
}
public configFileDiagnosticsReceived(file: Uri, diagnostics: Diagnostic[]): void {
@ -88,9 +101,11 @@ export default class DiagnosticsManager {
return;
}
const semanticDiagnostics = this.semanticDiagnostics.get(file);
const syntaxDiagnostics = this.syntaxDiagnostics.get(file);
this.currentDiagnostics.set(file, semanticDiagnostics.concat(syntaxDiagnostics));
const allDiagnostics = allDiagnosticKinds.reduce((sum, kind) => {
sum.push(...this.diagnostics.get(kind)!.get(file));
return sum;
}, [] as Diagnostic[]);
this.currentDiagnostics.set(file, allDiagnostics);
}
public getDiagnostics(file: Uri): Diagnostic[] {

View file

@ -36,7 +36,7 @@ const directives: Directive[] = [
export default class DirectiveCommentCompletionProvider implements CompletionItemProvider {
constructor(
private client: ITypeScriptServiceClient,
private readonly client: ITypeScriptServiceClient,
) { }
public provideCompletionItems(

Some files were not shown because too many files have changed in this diff Show more