提交 45ad5412 编写于 作者: A Alex Dima

Extract InplaceReplaceSupport to its own file

上级 f96ba9ed
......@@ -11,11 +11,11 @@ import {computeLinks} from 'vs/editor/common/modes/linkComputer';
import {DiffComputer} from 'vs/editor/common/diff/diffComputer';
import {DefaultFilter} from 'vs/editor/common/modes/modesFilters';
import {TextModel} from 'vs/editor/common/model/textModel';
import {WorkerInplaceReplaceSupport} from 'vs/editor/common/modes/supports';
import {ValidationHelper} from 'vs/editor/common/worker/validationHelper';
import EditorCommon = require('vs/editor/common/editorCommon');
import Modes = require('vs/editor/common/modes');
import {TPromise} from 'vs/base/common/winjs.base';
import {WorkerInplaceReplaceSupport} from 'vs/editor/common/modes/supports/inplaceReplaceSupport';
export class AbstractModeWorker {
......
......@@ -149,32 +149,6 @@ export class FilteredLineContext implements Modes.ILineContext {
}
}
export class AbstractSupport {
private _mode:Modes.IMode;
constructor(mode:Modes.IMode) {
this._mode = mode;
}
public get mode() {
return this._mode;
}
}
//--- Tokenazation support implementation
function isFunction(something) {
return typeof something === 'function';
}
// TODO@Alex -> refactor to use `brackets` from language configuration
export function getBracketFor(tokenType:string, tokenText:string, mode:Modes.IMode): Modes.Bracket {
if (tokenText === '{' || tokenText === '(' || tokenText === '[') {
......@@ -185,169 +159,3 @@ export function getBracketFor(tokenType:string, tokenText:string, mode:Modes.IMo
}
return Modes.Bracket.None;
}
export interface IReplaceSupportHelper {
valueSetReplace(valueSet: string[], value: string, up: boolean): string;
valueSetsReplace(valueSets: string[][], value: string, up: boolean): string;
}
class ReplaceSupportHelperImpl implements IReplaceSupportHelper {
public valueSetsReplace(valueSets:string[][], value:string, up:boolean):string {
var result:string = null;
for (let i = 0, len = valueSets.length; result === null && i < len; i++) {
result = this.valueSetReplace(valueSets[i], value, up);
}
return result;
}
public valueSetReplace(valueSet:string[], value:string, up:boolean):string {
var idx = valueSet.indexOf(value);
if(idx >= 0) {
idx += up ? +1 : -1;
if(idx < 0) {
idx = valueSet.length - 1;
} else {
idx %= valueSet.length;
}
return valueSet[idx];
}
return null;
}
}
export var ReplaceSupport: IReplaceSupportHelper = new ReplaceSupportHelperImpl();
export interface IInplaceReplaceSupportCustomization {
textReplace?: (value: string, up: boolean) => string;
navigateValueSetFallback?: (resource: URI, range: EditorCommon.IRange, up: boolean) => TPromise<Modes.IInplaceReplaceSupportResult>;
}
export class AbstractInplaceReplaceSupport implements Modes.IInplaceReplaceSupport {
private defaults: {
textReplace: boolean;
navigateValueSetFallback: boolean;
};
private customization:IInplaceReplaceSupportCustomization;
constructor(customization: IInplaceReplaceSupportCustomization = null) {
this.defaults = {
textReplace: !customization || !isFunction(customization.textReplace),
navigateValueSetFallback: !customization || !isFunction(customization.navigateValueSetFallback)
};
this.customization = customization;
}
public navigateValueSet(resource:URI, range:EditorCommon.IRange, up:boolean):TPromise<Modes.IInplaceReplaceSupportResult> {
var result = this.doNavigateValueSet(resource, range, up, true);
if (result && result.value && result.range) {
return TPromise.as(result);
}
if (this.defaults.navigateValueSetFallback) {
return TPromise.as(null);
}
return this.customization.navigateValueSetFallback(resource, range, up);
}
private doNavigateValueSet(resource:URI, range:EditorCommon.IRange, up:boolean, selection:boolean):Modes.IInplaceReplaceSupportResult {
var model = this.getModel(resource),
result:Modes.IInplaceReplaceSupportResult = { range:null, value: null },
text:string;
if(selection) {
// Replace selection
if(range.startColumn === range.endColumn) {
range.endColumn += 1;
}
text = model.getValueInRange(range);
result.range = range;
} else {
// Replace word
var position = { lineNumber: range.startLineNumber, column: range.startColumn };
var wordPos = model.getWordAtPosition(position);
if(!wordPos || wordPos.startColumn === -1) {
return null;
}
text = wordPos.word;
result.range = { startLineNumber : range.startLineNumber, endLineNumber: range.endLineNumber, startColumn: wordPos.startColumn, endColumn: wordPos.endColumn };
}
// Try to replace numbers or text
var numberResult = this.numberReplace(text, up);
if(numberResult !== null) {
result.value = numberResult;
} else {
var textResult = this.textReplace(text, up);
if(textResult !== null) {
result.value = textResult;
} else if(selection) {
return this.doNavigateValueSet(resource, range, up, false);
}
}
return result;
}
private numberReplace(value:string, up:boolean):string {
var precision = Math.pow(10, value.length - (value.lastIndexOf('.') + 1)),
n1 = Number(value),
n2 = parseFloat(value);
if(!isNaN(n1) && !isNaN(n2) && n1 === n2) {
if(n1 === 0 && !up) {
return null; // don't do negative
// } else if(n1 === 9 && up) {
// return null; // don't insert 10 into a number
} else {
n1 = Math.floor(n1 * precision);
n1 += up ? precision : -precision;
return String(n1 / precision);
}
}
return null;
}
private _defaultValueSet: string[][] = [
['true', 'false'],
['True', 'False'],
['Private', 'Public', 'Friend', 'ReadOnly', 'Partial', 'Protected', 'WriteOnly'],
['public', 'protected', 'private'],
];
private textReplace(value:string, up:boolean):string {
if (this.defaults.textReplace) {
return ReplaceSupport.valueSetsReplace(this._defaultValueSet, value, up);
}
return this.customization.textReplace(value, up)
|| ReplaceSupport.valueSetsReplace(this._defaultValueSet, value, up);
}
protected getModel(resource:URI): EditorCommon.ITokenizedModel {
throw new Error('Not implemented');
}
}
export class WorkerInplaceReplaceSupport extends AbstractInplaceReplaceSupport {
private resourceService: IResourceService;
constructor(resourceService: IResourceService, customization: IInplaceReplaceSupportCustomization = null) {
super(customization);
this.resourceService = resourceService;
}
protected getModel(resource:URI): EditorCommon.ITokenizedModel {
return this.resourceService.get(resource);
}
}
/*---------------------------------------------------------------------------------------------
* 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 {TPromise} from 'vs/base/common/winjs.base';
import Modes = require('vs/editor/common/modes');
import EditorCommon = require('vs/editor/common/editorCommon');
import {IResourceService} from 'vs/editor/common/services/resourceService';
import URI from 'vs/base/common/uri';
export interface IReplaceSupportHelper {
valueSetReplace(valueSet: string[], value: string, up: boolean): string;
valueSetsReplace(valueSets: string[][], value: string, up: boolean): string;
}
class ReplaceSupportHelperImpl implements IReplaceSupportHelper {
public valueSetsReplace(valueSets:string[][], value:string, up:boolean):string {
var result:string = null;
for (let i = 0, len = valueSets.length; result === null && i < len; i++) {
result = this.valueSetReplace(valueSets[i], value, up);
}
return result;
}
public valueSetReplace(valueSet:string[], value:string, up:boolean):string {
var idx = valueSet.indexOf(value);
if(idx >= 0) {
idx += up ? +1 : -1;
if(idx < 0) {
idx = valueSet.length - 1;
} else {
idx %= valueSet.length;
}
return valueSet[idx];
}
return null;
}
}
export var ReplaceSupport: IReplaceSupportHelper = new ReplaceSupportHelperImpl();
function isFunction(something) {
return typeof something === 'function';
}
export interface IInplaceReplaceSupportCustomization {
textReplace?: (value: string, up: boolean) => string;
navigateValueSetFallback?: (resource: URI, range: EditorCommon.IRange, up: boolean) => TPromise<Modes.IInplaceReplaceSupportResult>;
}
export class AbstractInplaceReplaceSupport implements Modes.IInplaceReplaceSupport {
private defaults: {
textReplace: boolean;
navigateValueSetFallback: boolean;
};
private customization:IInplaceReplaceSupportCustomization;
constructor(customization: IInplaceReplaceSupportCustomization = null) {
this.defaults = {
textReplace: !customization || !isFunction(customization.textReplace),
navigateValueSetFallback: !customization || !isFunction(customization.navigateValueSetFallback)
};
this.customization = customization;
}
public navigateValueSet(resource:URI, range:EditorCommon.IRange, up:boolean):TPromise<Modes.IInplaceReplaceSupportResult> {
var result = this.doNavigateValueSet(resource, range, up, true);
if (result && result.value && result.range) {
return TPromise.as(result);
}
if (this.defaults.navigateValueSetFallback) {
return TPromise.as(null);
}
return this.customization.navigateValueSetFallback(resource, range, up);
}
private doNavigateValueSet(resource:URI, range:EditorCommon.IRange, up:boolean, selection:boolean):Modes.IInplaceReplaceSupportResult {
var model = this.getModel(resource),
result:Modes.IInplaceReplaceSupportResult = { range:null, value: null },
text:string;
if(selection) {
// Replace selection
if(range.startColumn === range.endColumn) {
range.endColumn += 1;
}
text = model.getValueInRange(range);
result.range = range;
} else {
// Replace word
var position = { lineNumber: range.startLineNumber, column: range.startColumn };
var wordPos = model.getWordAtPosition(position);
if(!wordPos || wordPos.startColumn === -1) {
return null;
}
text = wordPos.word;
result.range = { startLineNumber : range.startLineNumber, endLineNumber: range.endLineNumber, startColumn: wordPos.startColumn, endColumn: wordPos.endColumn };
}
// Try to replace numbers or text
var numberResult = this.numberReplace(text, up);
if(numberResult !== null) {
result.value = numberResult;
} else {
var textResult = this.textReplace(text, up);
if(textResult !== null) {
result.value = textResult;
} else if(selection) {
return this.doNavigateValueSet(resource, range, up, false);
}
}
return result;
}
private numberReplace(value:string, up:boolean):string {
var precision = Math.pow(10, value.length - (value.lastIndexOf('.') + 1)),
n1 = Number(value),
n2 = parseFloat(value);
if(!isNaN(n1) && !isNaN(n2) && n1 === n2) {
if(n1 === 0 && !up) {
return null; // don't do negative
// } else if(n1 === 9 && up) {
// return null; // don't insert 10 into a number
} else {
n1 = Math.floor(n1 * precision);
n1 += up ? precision : -precision;
return String(n1 / precision);
}
}
return null;
}
private _defaultValueSet: string[][] = [
['true', 'false'],
['True', 'False'],
['Private', 'Public', 'Friend', 'ReadOnly', 'Partial', 'Protected', 'WriteOnly'],
['public', 'protected', 'private'],
];
private textReplace(value:string, up:boolean):string {
if (this.defaults.textReplace) {
return ReplaceSupport.valueSetsReplace(this._defaultValueSet, value, up);
}
return this.customization.textReplace(value, up)
|| ReplaceSupport.valueSetsReplace(this._defaultValueSet, value, up);
}
protected getModel(resource:URI): EditorCommon.ITokenizedModel {
throw new Error('Not implemented');
}
}
export class WorkerInplaceReplaceSupport extends AbstractInplaceReplaceSupport {
private resourceService: IResourceService;
constructor(resourceService: IResourceService, customization: IInplaceReplaceSupportCustomization = null) {
super(customization);
this.resourceService = resourceService;
}
protected getModel(resource:URI): EditorCommon.ITokenizedModel {
return this.resourceService.get(resource);
}
}
......@@ -27,6 +27,7 @@ import supports = require('vs/editor/common/modes/supports');
import {IMarker, IMarkerData} from 'vs/platform/markers/common/markers';
import {IMarkerService} from 'vs/platform/markers/common/markers';
import {IResourceService} from 'vs/editor/common/services/resourceService';
import {WorkerInplaceReplaceSupport} from 'vs/editor/common/modes/supports/inplaceReplaceSupport';
export class CSSWorker extends AbstractModeWorker {
......@@ -45,7 +46,7 @@ export class CSSWorker extends AbstractModeWorker {
}
protected _createInPlaceReplaceSupport(): Modes.IInplaceReplaceSupport {
return new supports.WorkerInplaceReplaceSupport(this.resourceService, this);
return new WorkerInplaceReplaceSupport(this.resourceService, this);
}
public createLanguageService(resourceService:IResourceService, modeId:string): languageService.CSSLanguageService {
......
......@@ -33,6 +33,7 @@ import {ISchemaContributions} from 'vs/platform/jsonschemas/common/jsonContribut
import {IResourceService} from 'vs/editor/common/services/resourceService';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {JSONLocation} from './parser/jsonLocation';
import {WorkerInplaceReplaceSupport, ReplaceSupport} from 'vs/editor/common/modes/supports/inplaceReplaceSupport';
export interface IOptionsSchema {
/**
......@@ -103,7 +104,7 @@ export class JSONWorker extends AbstractModeWorker implements Modes.IExtraInfoSu
}
protected _createInPlaceReplaceSupport(): Modes.IInplaceReplaceSupport {
return new supports.WorkerInplaceReplaceSupport(this.resourceService, this);
return new WorkerInplaceReplaceSupport(this.resourceService, this);
}
/**
......@@ -320,7 +321,7 @@ export class JSONWorker extends AbstractModeWorker implements Modes.IExtraInfoSu
}
public textReplace(value:string, up:boolean):string {
return supports.ReplaceSupport.valueSetReplace(['true', 'false'], value, up);
return ReplaceSupport.valueSetReplace(['true', 'false'], value, up);
}
public format(resource: URI, range: EditorCommon.IRange, options: Modes.IFormattingOptions): WinJS.TPromise<EditorCommon.ISingleEditOperation[]> {
......
......@@ -32,6 +32,7 @@ import emitting = require('vs/languages/typescript/common/features/emitting');
import rename = require('vs/languages/typescript/common/features/rename');
import {IResourceService, ResourceEvents, IResourceAddedEvent, IResourceRemovedEvent} from 'vs/editor/common/services/resourceService';
import {IMarker, IMarkerService} from 'vs/platform/markers/common/markers';
import {WorkerInplaceReplaceSupport, ReplaceSupport} from 'vs/editor/common/modes/supports/inplaceReplaceSupport';
export class TypeScriptWorker2 extends AbstractModeWorker {
......@@ -150,7 +151,7 @@ export class TypeScriptWorker2 extends AbstractModeWorker {
// ---- Implementation of various IXYZSupports
protected _createInPlaceReplaceSupport(): Modes.IInplaceReplaceSupport {
return new supports.WorkerInplaceReplaceSupport(this.resourceService, this);
return new WorkerInplaceReplaceSupport(this.resourceService, this);
}
public doValidate(resource: URI): void {
......@@ -257,7 +258,7 @@ export class TypeScriptWorker2 extends AbstractModeWorker {
['string', 'number', 'boolean', 'void', 'any'],
['private', 'public']
];
return supports.ReplaceSupport.valueSetsReplace(valueSets, value, up);
return ReplaceSupport.valueSetsReplace(valueSets, value, up);
}
public findReferences(resource: URI, position: EditorCommon.IPosition, includeDeclaration: boolean): winjs.TPromise<Modes.IReference[]> {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册