提交 78e11f23 编写于 作者: J Johannes Rieken

commands: executeFormatDocumentProvider, executeFormatRangeProvider

上级 a7f719e4
...@@ -5,10 +5,67 @@ ...@@ -5,10 +5,67 @@
'use strict'; 'use strict';
import {IFormattingSupport} from 'vs/editor/common/modes'; import {IFormattingSupport, IFormattingOptions} from 'vs/editor/common/modes';
import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry';
import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors';
import URI from 'vs/base/common/uri';
import {IAction, Action} from 'vs/base/common/actions';
import {IModelService} from 'vs/editor/common/services/modelService';
import {TPromise} from 'vs/base/common/winjs.base';
import {IModel, IRange, IPosition, ISingleEditOperation} from 'vs/editor/common/editorCommon';
import {Range} from 'vs/editor/common/core/range';
import {CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions';
export const FormatRegistry = new LanguageFeatureRegistry<IFormattingSupport>('formattingSupport'); export const FormatRegistry = new LanguageFeatureRegistry<IFormattingSupport>('formattingSupport');
export const FormatOnTypeRegistry = new LanguageFeatureRegistry<IFormattingSupport>('formattingSupport'); export const FormatOnTypeRegistry = new LanguageFeatureRegistry<IFormattingSupport>('formattingSupport');
export {IFormattingSupport}; export {IFormattingSupport};
\ No newline at end of file
export function formatRange(model: IModel, range: IRange, options: IFormattingOptions): TPromise<ISingleEditOperation[]> {
const support = FormatRegistry.ordered(model)[0];
if (!support) {
return;
}
return support.formatRange(model.getAssociatedResource(), range, options);
}
export function formatDocument(model: IModel, options: IFormattingOptions): TPromise<ISingleEditOperation[]> {
const support = FormatRegistry.ordered(model)[0];
if (!support) {
return;
}
if (typeof support.formatDocument !== 'function') {
if (typeof support.formatRange === 'function') {
return formatRange(model, model.getFullModelRange(), options);
} else {
return;
}
}
return support.formatDocument(model.getAssociatedResource(), options);
}
CommonEditorRegistry.registerLanguageCommand('_executeFormatRangeProvider', function(accessor, args) {
const {resource, range, options} = args;
if (!URI.isURI(resource) || !Range.isIRange(range)) {
throw illegalArgument();
}
const model = accessor.get(IModelService).getModel(resource);
if (!model) {
throw illegalArgument('resource');
}
return formatRange(model, range, options);
});
CommonEditorRegistry.registerLanguageCommand('_executeFormatDocumentProvider', function(accessor, args) {
const {resource, options} = args;
if (!URI.isURI(resource)) {
throw illegalArgument('resource');
}
const model = accessor.get(IModelService).getModel(resource);
if (!model) {
throw illegalArgument('resource');
}
return formatDocument(model, options)
});
\ No newline at end of file
...@@ -15,7 +15,7 @@ import formatCommand = require('./formatCommand'); ...@@ -15,7 +15,7 @@ import formatCommand = require('./formatCommand');
import {Range} from 'vs/editor/common/core/range'; import {Range} from 'vs/editor/common/core/range';
import {INullService} from 'vs/platform/instantiation/common/instantiation'; import {INullService} from 'vs/platform/instantiation/common/instantiation';
import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; import {KeyMod, KeyCode} from 'vs/base/common/keyCodes';
import {FormatOnTypeRegistry, FormatRegistry, IFormattingSupport} from '../common/format'; import {FormatOnTypeRegistry, FormatRegistry, IFormattingSupport, formatRange, formatDocument} from '../common/format';
interface IFormatOnTypeResult { interface IFormatOnTypeResult {
range: EditorCommon.IEditorRange; range: EditorCommon.IEditorRange;
...@@ -170,31 +170,19 @@ export class FormatAction extends EditorAction { ...@@ -170,31 +170,19 @@ export class FormatAction extends EditorAction {
public run(): TPromise<boolean> { public run(): TPromise<boolean> {
var model = this.editor.getModel(), const model = this.editor.getModel(),
formattingSupport = FormatRegistry.ordered(model)[0], editorSelection = this.editor.getSelection(),
canFormatRange = typeof formattingSupport.formatRange === 'function', options = this.editor.getIndentationOptions();
canFormatDocument = typeof formattingSupport.formatDocument === 'function',
editorSelection = this.editor.getSelection(); let formattingPromise: TPromise<EditorCommon.ISingleEditOperation[]>;
var options = this.editor.getIndentationOptions(),
formattingPromise: TPromise<EditorCommon.ISingleEditOperation[]>;
if(canFormatRange) {
// format a selection/range
var formatRange: EditorCommon.IEditorRange = editorSelection;
if(!formatRange.isEmpty()) {
// Fix the selection to include the entire line to improve formatting results
formatRange.startColumn = 1;
} else {
formatRange = model.getFullModelRange();
}
formattingPromise = formattingSupport.formatRange(model.getAssociatedResource(), formatRange, options);
} else if(canFormatDocument) { if (editorSelection.isEmpty()) {
// format the whole document formattingPromise = formatDocument(model, options);
formattingPromise = formattingSupport.formatDocument(model.getAssociatedResource(), options);
} else { } else {
// broken support? formattingPromise = formatRange(model, editorSelection, options);
}
if (!formattingPromise) {
return TPromise.as(false); return TPromise.as(false);
} }
......
...@@ -48,9 +48,9 @@ import {ICodeLensData} from 'vs/editor/contrib/codelens/common/codelens'; ...@@ -48,9 +48,9 @@ import {ICodeLensData} from 'vs/editor/contrib/codelens/common/codelens';
// vscode.executeCompletionItemProvider // vscode.executeCompletionItemProvider
// vscode.executeCodeActionProvider // vscode.executeCodeActionProvider
// vscode.executeCodeLensProvider // vscode.executeCodeLensProvider
// vscode.executeFormatDocumentProvider // vscode.executeFormatDocumentProvider
// vscode.executeFormatRangeProvider // vscode.executeFormatRangeProvider
// vscode.executeFormatOnTypeProvider // vscode.executeFormatOnTypeProvider
export class ExtHostLanguageFeatureCommands { export class ExtHostLanguageFeatureCommands {
...@@ -72,6 +72,8 @@ export class ExtHostLanguageFeatureCommands { ...@@ -72,6 +72,8 @@ export class ExtHostLanguageFeatureCommands {
this._register('vscode.executeCompletionItemProvider', this._executeCompletionItemProvider); this._register('vscode.executeCompletionItemProvider', this._executeCompletionItemProvider);
this._register('vscode.executeCodeActionProvider', this._executeCodeActionProvider); this._register('vscode.executeCodeActionProvider', this._executeCodeActionProvider);
this._register('vscode.executeCodeLensProvider', this._executeCodeLensProvider); this._register('vscode.executeCodeLensProvider', this._executeCodeLensProvider);
this._register('vscode.executeFormatDocumentProvider', this._executeFormatDocumentProvider);
this._register('vscode.executeFormatRangeProvider', this._executeFormatRangeProvider);
} }
private _register(id: string, callback: (...args: any[]) => any): void { private _register(id: string, callback: (...args: any[]) => any): void {
...@@ -217,10 +219,7 @@ export class ExtHostLanguageFeatureCommands { ...@@ -217,10 +219,7 @@ export class ExtHostLanguageFeatureCommands {
} }
private _executeCodeLensProvider(resource: URI): Thenable<vscode.CodeLens[]>{ private _executeCodeLensProvider(resource: URI): Thenable<vscode.CodeLens[]>{
const args = { const args = { resource };
resource
};
return this._commands.executeCommand<ICodeLensData[]>('_executeCodeLensProvider', args).then(value => { return this._commands.executeCommand<ICodeLensData[]>('_executeCodeLensProvider', args).then(value => {
if (Array.isArray(value)) { if (Array.isArray(value)) {
return value.map(item => { return value.map(item => {
...@@ -230,4 +229,29 @@ export class ExtHostLanguageFeatureCommands { ...@@ -230,4 +229,29 @@ export class ExtHostLanguageFeatureCommands {
} }
}); });
} }
private _executeFormatDocumentProvider(resource: URI, options: vscode.FormattingOptions): Thenable<vscode.TextEdit[]> {
const args = {
resource,
options
};
return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatDocumentProvider', args).then(value => {
if (Array.isArray(value)) {
return value.map(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text));
}
});
}
private _executeFormatRangeProvider(resource: URI, range: types.Range, options: vscode.FormattingOptions): Thenable<vscode.TextEdit[]> {
const args = {
resource,
range: typeConverters.fromRange(range),
options
};
return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatRangeProvider', args).then(value => {
if (Array.isArray(value)) {
return value.map(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text));
}
});
}
} }
\ No newline at end of file
...@@ -37,6 +37,7 @@ import {getNavigateToItems} from 'vs/workbench/parts/search/common/search'; ...@@ -37,6 +37,7 @@ import {getNavigateToItems} from 'vs/workbench/parts/search/common/search';
import {rename} from 'vs/editor/contrib/rename/common/rename'; import {rename} from 'vs/editor/contrib/rename/common/rename';
import {getParameterHints} from 'vs/editor/contrib/parameterHints/common/parameterHints'; import {getParameterHints} from 'vs/editor/contrib/parameterHints/common/parameterHints';
import {suggest} from 'vs/editor/contrib/suggest/common/suggest'; import {suggest} from 'vs/editor/contrib/suggest/common/suggest';
import {formatDocument, formatRange} from 'vs/editor/contrib/format/common/format';
const defaultSelector = { scheme: 'far' }; const defaultSelector = { scheme: 'far' };
const model: EditorCommon.IModel = new EditorModel( const model: EditorCommon.IModel = new EditorModel(
...@@ -907,4 +908,66 @@ suite('ExtHostLanguageFeatures', function() { ...@@ -907,4 +908,66 @@ suite('ExtHostLanguageFeatures', function() {
}); });
}); });
}); });
// --- format
test('Format Doc, data conversion', function(done) {
disposables.push(extHost.registerDocumentFormattingEditProvider(defaultSelector, <vscode.DocumentFormattingEditProvider>{
provideDocumentFormattingEdits(): any {
return [new types.TextEdit(new types.Range(0, 0, 1, 1), 'testing')];
}
}));
threadService.sync().then(() => {
formatDocument(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: 2, endColumn: 2 });
done();
});
});
});
test('Format Doc, evil provider', function(done) {
disposables.push(extHost.registerDocumentFormattingEditProvider(defaultSelector, <vscode.DocumentFormattingEditProvider>{
provideDocumentFormattingEdits(): any {
throw new Error('evil');
}
}));
threadService.sync().then(() => {
formatDocument(model, { insertSpaces: true, tabSize: 4 }).then(undefined, err => done());
});
});
test('Format Range, data conversion', function(done) {
disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultSelector, <vscode.DocumentRangeFormattingEditProvider>{
provideDocumentRangeFormattingEdits(): any {
return [new types.TextEdit(new types.Range(0, 0, 1, 1), 'testing')];
}
}));
threadService.sync().then(() => {
formatRange(model, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }, { 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: 2, endColumn: 2 });
done();
});
});
})
test('Format Range, evil provider', function(done) {
disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultSelector, <vscode.DocumentRangeFormattingEditProvider>{
provideDocumentRangeFormattingEdits(): any {
throw new Error('evil');
}
}));
threadService.sync().then(() => {
formatRange(model, { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 }, { insertSpaces: true, tabSize: 4 }).then(undefined, err => done());
});
})
}); });
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册