Merge pull request #13880 from Microsoft/joh/fmtconfig

enable/disable toggles for default formatters
This commit is contained in:
Johannes Rieken 2016-10-17 17:04:32 +02:00 committed by GitHub
commit 262b398026
13 changed files with 160 additions and 52 deletions

View file

@ -6,7 +6,7 @@
import * as path from 'path';
import { languages, ExtensionContext, IndentAction } from 'vscode';
import { languages, workspace, ExtensionContext, IndentAction } from 'vscode';
import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient';
import { EMPTY_ELEMENTS } from './htmlEmptyTagsShared';
@ -36,6 +36,7 @@ export function activate(context: ExtensionContext) {
configurationSection: ['html'],
},
initializationOptions: {
['format.enable']: workspace.getConfiguration('html').get('format.enable')
}
};

View file

@ -18,25 +18,56 @@
"install-client-next": "npm install vscode-languageclient@next -f -S",
"install-client-local": "npm install ../../../vscode-languageserver-node/client -f -S"
},
"contributes": {
"languages": [{
"id": "html",
"extensions": [ ".html", ".htm", ".shtml", ".xhtml", ".mdoc", ".jsp", ".asp", ".aspx", ".jshtm", ".vue" ],
"aliases": [ "HTML", "htm", "html", "xhtml" ],
"mimetypes": ["text/html", "text/x-jshtm", "text/template", "text/ng-template", "application/xhtml+xml"],
"configuration": "./language-configuration.json"
}],
"grammars": [{
"language": "html",
"scopeName": "text.html.basic",
"path": "./syntaxes/html.json"
}],
"contributes": {
"languages": [
{
"id": "html",
"extensions": [
".html",
".htm",
".shtml",
".xhtml",
".mdoc",
".jsp",
".asp",
".aspx",
".jshtm",
".vue"
],
"aliases": [
"HTML",
"htm",
"html",
"xhtml"
],
"mimetypes": [
"text/html",
"text/x-jshtm",
"text/template",
"text/ng-template",
"application/xhtml+xml"
],
"configuration": "./language-configuration.json"
}
],
"grammars": [
{
"language": "html",
"scopeName": "text.html.basic",
"path": "./syntaxes/html.json"
}
],
"configuration": {
"id": "html",
"order": 20,
"type": "object",
"title": "HTML",
"properties": {
"html.format.enable": {
"type": "boolean",
"default": true,
"description": "Enable/disable default HTML formatter"
},
"html.format.wrapLineLength": {
"type": "integer",
"default": 120,
@ -108,4 +139,4 @@
"vscode-languageclient": "^2.6.0-next.1",
"vscode-nls": "^1.0.7"
}
}
}

View file

@ -48,8 +48,7 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
textDocumentSync: documents.syncKind,
completionProvider: { resolveProvider: false, triggerCharacters: ['.', ':', '<', '"', '=', '/'] },
documentHighlightProvider: true,
documentRangeFormattingProvider: true,
documentFormattingProvider: true,
documentRangeFormattingProvider: params.initializationOptions['format.enable'],
documentLinkProvider: true
}
};
@ -106,11 +105,6 @@ function getFormattingOptions(formatParams: FormattingOptions) {
return merge(formatParams, merge(formatSettings, {}));
}
connection.onDocumentFormatting(formatParams => {
let document = documents.get(formatParams.textDocument.uri);
return languageService.format(document, null, getFormattingOptions(formatParams.options));
});
connection.onDocumentRangeFormatting(formatParams => {
let document = documents.get(formatParams.textDocument.uri);
return languageService.format(document, formatParams.range, getFormattingOptions(formatParams.options));

View file

@ -61,7 +61,8 @@ export function activate(context: ExtensionContext) {
fileEvents: workspace.createFileSystemWatcher('**/*.json')
},
initializationOptions: {
languageIds
languageIds,
['format.enable']: workspace.getConfiguration('json').get('format.enable')
}
};

View file

@ -92,6 +92,11 @@
}
}
}
},
"json.format.enable": {
"type": "boolean",
"default": true,
"description": "Enable/disable default JSON formatter"
}
}
}
@ -101,4 +106,4 @@
"vscode-languageclient": "^2.4.2-next.22",
"vscode-nls": "^1.0.7"
}
}
}

View file

@ -64,8 +64,7 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
completionProvider: { resolveProvider: true, triggerCharacters: ['"', ':'] },
hoverProvider: true,
documentSymbolProvider: true,
documentRangeFormattingProvider: true,
documentFormattingProvider: true
documentRangeFormattingProvider: params.initializationOptions['format.enable']
}
};
});
@ -278,11 +277,6 @@ connection.onDocumentSymbol(documentSymbolParams => {
return languageService.findDocumentSymbols(document, jsonDocument);
});
connection.onDocumentFormatting(formatParams => {
let document = documents.get(formatParams.textDocument.uri);
return languageService.format(document, null, formatParams.options);
});
connection.onDocumentRangeFormatting(formatParams => {
let document = documents.get(formatParams.textDocument.uri);
return languageService.format(document, formatParams.range, formatParams.options);

View file

@ -6,7 +6,7 @@
"author": "Microsoft Corporation",
"license": "MIT",
"publisher": "vscode",
"aiKey":"AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"engines": {
"vscode": "*"
},
@ -74,7 +74,10 @@
"order": 20,
"properties": {
"typescript.tsdk": {
"type": ["string", "null"],
"type": [
"string",
"null"
],
"default": null,
"description": "%typescript.tsdk.desc%"
},
@ -83,19 +86,23 @@
"default": false,
"description": "%typescript.experimentalAutomaticTypeAcquisition%"
},
"typescript.check.workspaceVersion" :{
"typescript.check.workspaceVersion": {
"type": "boolean",
"default": true,
"description": "%typescript.check.workspaceVersion%"
},
"typescript.check.tscVersion" :{
"typescript.check.tscVersion": {
"type": "boolean",
"default": true,
"description": "%typescript.check.tscVersion%"
},
"typescript.tsserver.trace": {
"type": "string",
"enum": ["off", "messages", "verbose"],
"enum": [
"off",
"messages",
"verbose"
],
"default": "off",
"description": "%typescript.tsserver.trace%"
},
@ -109,6 +116,11 @@
"default": true,
"description": "%typescript.validate.enable%"
},
"typescript.format.enable": {
"type": "boolean",
"default": true,
"description": "%typescript.format.enable%"
},
"typescript.format.insertSpaceAfterCommaDelimiter": {
"type": "boolean",
"default": true,
@ -169,6 +181,11 @@
"default": true,
"description": "%javascript.validate.enable%"
},
"javascript.format.enable": {
"type": "boolean",
"default": true,
"description": "%javascript.format.enable%"
},
"javascript.format.insertSpaceAfterCommaDelimiter": {
"type": "boolean",
"default": true,

View file

@ -10,7 +10,9 @@
"typescript.check.tscVersion": "Check if a global install TypeScript compiler (e.g. tsc) differs from the used TypeScript language service.",
"typescript.tsserver.trace": "Enables tracing of messages send to the TS server",
"typescript.tsserver.experimentalAutoBuild": "Enables experimental auto build. Requires 1.9 dev or 2.x tsserver version and a restart of VS Code after changing it.",
"typescript.validate.enable": "Enable / disable TypeScript validation",
"typescript.validate.enable": "Enable/disable TypeScript validation",
"typescript.format.enable": "Enable/disable default TypeScript formatter",
"javascript.format.enable": "Enable/disable default JavaScript formatter",
"format.insertSpaceAfterCommaDelimiter": "Defines space handling after a comma delimiter",
"format.insertSpaceAfterSemicolonInForStatements": " Defines space handling after a semicolon in a for statement",
"format.insertSpaceBeforeAndAfterBinaryOperators": "Defines space handling after a binary operator",

View file

@ -11,6 +11,7 @@ import * as Proto from '../protocol';
import { ITypescriptServiceClient } from '../typescriptService';
interface Configuration {
enable: boolean;
insertSpaceAfterCommaDelimiter: boolean;
insertSpaceAfterSemicolonInForStatements: boolean;
insertSpaceBeforeAndAfterBinaryOperators: boolean;
@ -50,6 +51,7 @@ namespace Configuration {
export function def(): Configuration {
let result: Configuration = Object.create(null);
result.enable = true;
result.insertSpaceAfterCommaDelimiter = true;
result.insertSpaceAfterSemicolonInForStatements = true;
result.insertSpaceBeforeAndAfterBinaryOperators = true;
@ -86,6 +88,10 @@ export default class TypeScriptFormattingProvider implements DocumentRangeFormat
}
}
public isEnabled(): boolean {
return this.config.enable;
}
private ensureFormatOptions(document: TextDocument, options: FormattingOptions, token: CancellationToken): Promise<Proto.FormatCodeSettings> {
let key = document.uri.toString();
let currentOptions = this.formatOptions[key];

View file

@ -9,7 +9,7 @@
* ------------------------------------------------------------------------------------------ */
'use strict';
import { env, languages, commands, workspace, window, Uri, ExtensionContext, Memento, IndentAction, Diagnostic, DiagnosticCollection, Range, DocumentFilter } from 'vscode';
import { env, languages, commands, workspace, window, Uri, ExtensionContext, Memento, IndentAction, Diagnostic, DiagnosticCollection, Range, DocumentFilter, Disposable } from 'vscode';
// This must be the first statement otherwise modules might got loaded with
// the wrong locale.
@ -103,6 +103,7 @@ class LanguageProvider {
private completionItemProvider: CompletionItemProvider;
private formattingProvider: FormattingProvider;
private formattingProviderRegistration: Disposable;
private _validate: boolean;
@ -147,6 +148,9 @@ class LanguageProvider {
let renameProvider = new RenameProvider(client);
this.formattingProvider = new FormattingProvider(client);
this.formattingProvider.updateConfiguration(config);
if (this.formattingProvider.isEnabled) {
this.formattingProviderRegistration = languages.registerDocumentRangeFormattingEditProvider(this.description.modeIds, this.formattingProvider);
}
this.description.modeIds.forEach(modeId => {
let selector: DocumentFilter = { scheme: 'file', language: modeId };
@ -158,7 +162,6 @@ class LanguageProvider {
languages.registerDocumentSymbolProvider(selector, documentSymbolProvider);
languages.registerSignatureHelpProvider(selector, signatureHelpProvider, '(', ',');
languages.registerRenameProvider(selector, renameProvider);
languages.registerDocumentRangeFormattingEditProvider(selector, this.formattingProvider);
languages.registerOnTypeFormattingEditProvider(selector, this.formattingProvider, ';', '}', '\n');
languages.registerWorkspaceSymbolProvider(new WorkspaceSymbolProvider(client, modeId));
languages.setLanguageConfiguration(modeId, {
@ -209,6 +212,13 @@ class LanguageProvider {
}
if (this.formattingProvider) {
this.formattingProvider.updateConfiguration(config);
if (!this.formattingProvider.isEnabled() && this.formattingProviderRegistration) {
this.formattingProviderRegistration.dispose();
this.formattingProviderRegistration = undefined;
} else if (this.formattingProvider.isEnabled() && !this.formattingProviderRegistration) {
this.formattingProviderRegistration = languages.registerDocumentRangeFormattingEditProvider(this.description.modeIds, this.formattingProvider);
}
}
}

View file

@ -7,38 +7,58 @@
import { illegalArgument } from 'vs/base/common/errors';
import URI from 'vs/base/common/uri';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { TPromise } from 'vs/base/common/winjs.base';
import { Range } from 'vs/editor/common/core/range';
import { IReadOnlyModel, ISingleEditOperation } from 'vs/editor/common/editorCommon';
import { CommonEditorRegistry } from 'vs/editor/common/editorCommonExtensions';
import { DocumentFormattingEditProviderRegistry, DocumentRangeFormattingEditProviderRegistry, OnTypeFormattingEditProviderRegistry, FormattingOptions } from 'vs/editor/common/modes';
import { IModelService } from 'vs/editor/common/services/modelService';
import { asWinJsPromise } from 'vs/base/common/async';
import { asWinJsPromise, sequence } from 'vs/base/common/async';
import { Position } from 'vs/editor/common/core/position';
export function getDocumentRangeFormattingEdits(model: IReadOnlyModel, range: Range, options: FormattingOptions): TPromise<ISingleEditOperation[]> {
const [support] = DocumentRangeFormattingEditProviderRegistry.ordered(model);
if (!support) {
const providers = DocumentRangeFormattingEditProviderRegistry.ordered(model);
if (providers.length === 0) {
return TPromise.as(undefined);
}
return asWinJsPromise((token) => {
return support.provideDocumentRangeFormattingEdits(model, range, options, token);
});
let result: ISingleEditOperation[];
return sequence(providers.map(provider => {
if (isFalsyOrEmpty(result)) {
return () => {
return asWinJsPromise(token => provider.provideDocumentRangeFormattingEdits(model, range, options, token)).then(value => {
result = value;
}, err => {
// ignore
});
};
}
})).then(() => result);
}
export function getDocumentFormattingEdits(model: IReadOnlyModel, options: FormattingOptions): TPromise<ISingleEditOperation[]> {
const [support] = DocumentFormattingEditProviderRegistry.ordered(model);
const providers = DocumentFormattingEditProviderRegistry.ordered(model);
// try range formatters when no document formatter is registered
if (!support) {
if (providers.length === 0) {
return getDocumentRangeFormattingEdits(model, model.getFullModelRange(), options);
}
return asWinJsPromise((token) => {
return support.provideDocumentFormattingEdits(model, options, token);
});
let result: ISingleEditOperation[];
return sequence(providers.map(provider => {
if (isFalsyOrEmpty(result)) {
return () => {
return asWinJsPromise(token => provider.provideDocumentFormattingEdits(model, options, token)).then(value => {
result = value;
}, err => {
// ignore
});
};
}
})).then(() => result);
}
export function getOnTypeFormattingEdits(model: IReadOnlyModel, position: Position, ch: string, options: FormattingOptions): TPromise<ISingleEditOperation[]> {

4
src/vs/vscode.d.ts vendored
View file

@ -4074,6 +4074,10 @@ declare namespace vscode {
/**
* Register a formatting provider for a document range.
*
* *Note:* A document range provider is also a [document formatter](#DocumentFormattingEditProvider)
* which means there is no need to [register](registerDocumentFormattingEditProvider) a document
* formatter when also registering a range provider.
*
* Multiple providers can be registered for a language. In that case providers are sorted
* by their [score](#languages.match) and the best-matching provider is used. Failure
* of the selected provider will cause a failure of the whole operation.

View file

@ -884,7 +884,30 @@ suite('ExtHostLanguageFeatures', function () {
}));
return threadService.sync().then(() => {
return getDocumentFormattingEdits(model, { insertSpaces: true, tabSize: 4 }).then(_ => { throw new Error(); }, err => { });
return getDocumentFormattingEdits(model, { insertSpaces: true, tabSize: 4 });
});
});
test('Format Doc, order', function () {
disposables.push(extHost.registerDocumentFormattingEditProvider(defaultSelector, <vscode.DocumentFormattingEditProvider>{
provideDocumentFormattingEdits(): any {
return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'testing')];
}
}));
disposables.push(extHost.registerDocumentFormattingEditProvider(defaultSelector, <vscode.DocumentFormattingEditProvider>{
provideDocumentFormattingEdits(): any {
return undefined;
}
}));
return threadService.sync().then(() => {
return getDocumentFormattingEdits(model, { insertSpaces: true, tabSize: 4 }).then(value => {
assert.equal(value.length, 1);
let [first] = value;
assert.equal(first.text, 'testing');
assert.deepEqual(first.range, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 });
});
});
});
@ -933,7 +956,7 @@ suite('ExtHostLanguageFeatures', function () {
}));
return threadService.sync().then(() => {
return getDocumentRangeFormattingEdits(model, new EditorRange(1, 1, 1, 1), { insertSpaces: true, tabSize: 4 }).then(_ => { throw new Error(); }, err => { });
return getDocumentRangeFormattingEdits(model, new EditorRange(1, 1, 1, 1), { insertSpaces: true, tabSize: 4 });
});
});