提交 58da79c8 编写于 作者: J Johannes Rieken

make sure adjust indentation creates a copy of the snippet, #16037

上级 823b3db4
......@@ -151,6 +151,13 @@ export class Text extends Marker {
len(): number {
return this.string.length;
}
with(string: string): Text {
if (this.string !== string) {
return new Text(string);
} else {
return this;
}
}
}
export class Placeholder extends Marker {
......@@ -160,6 +167,9 @@ export class Placeholder extends Marker {
toString() {
return Marker.toString(this.defaultValue);
}
with(defaultValue: Marker[]): Placeholder {
return new Placeholder(this.name, defaultValue);
}
}
export class Variable extends Marker {
......@@ -169,14 +179,17 @@ export class Variable extends Marker {
constructor(public name: string = '', public defaultValue: Marker[]) {
super();
}
get isDefined(): boolean {
return this.resolvedValue !== undefined;
}
toString() {
return this.isDefined ? this.resolvedValue : Marker.toString(this.defaultValue);
}
with(defaultValue: Marker[]): Variable {
let ret = new Variable(this.name, defaultValue);
ret.resolvedValue = this.resolvedValue;
return ret;
}
}
export function walk(marker: Marker[], visitor: (marker: Marker) => boolean): void {
const stack = [...marker];
......@@ -234,26 +247,41 @@ export class TextmateSnippet {
return map;
}
adjustIndentation(normalizer: (whitespace: string) => string): void {
withIndentation(normalizer: (whitespace: string) => string): TextmateSnippet {
// create a new snippet because this can be
// different for each and every cursor
const newMarker = [...this.marker];
TextmateSnippet._adjustIndentation(newMarker, normalizer);
return new TextmateSnippet(newMarker);
}
walk(this.marker, candidate => {
private static _adjustIndentation(marker: Marker[], normalizer: (whitespace: string) => string): void {
for (let i = 0; i < marker.length; i++) {
const candidate = marker[i];
if (candidate instanceof Text) {
//check for newline characters and adjust indent
let regex = /\r\n|\r|\n/g;
let match: RegExpMatchArray;
while (match = regex.exec(candidate.string)) {
let value = candidate.string;
while (match = regex.exec(value)) {
let pos = regex.lastIndex;
let whitespace = getLeadingWhitespace(candidate.string, pos);
let whitespace = getLeadingWhitespace(value, pos);
let normalized = normalizer(whitespace);
if (whitespace !== normalized) {
candidate.string = candidate.string.substr(0, pos)
value = value.substr(0, pos)
+ normalized
+ candidate.string.substr(pos + whitespace.length);
+ value.substr(pos + whitespace.length);
marker[i] = candidate.with(value);
}
}
} else if (candidate instanceof Placeholder || candidate instanceof Variable) {
// recurse with a copied array
let children = [...candidate.defaultValue];
TextmateSnippet._adjustIndentation(children, normalizer);
marker[i] = candidate.with(children);
}
return true;
});
}
}
}
......
......@@ -363,21 +363,24 @@ suite('SnippetParser', () => {
assert.equal(snippet.offset(array[0]), 3);
});
test('TextmateSnippet#adjustIndentation', () => {
test('TextmateSnippet#withIndentation', () => {
let snippet = SnippetParser.parse('foo\n bar');
assert.equal(Marker.toString(snippet.marker), 'foo\n bar');
snippet.adjustIndentation(s => s.replace(/ /, '\t'));
assert.equal(Marker.toString(snippet.marker), 'foo\n\tbar');
let newSnippet = snippet.withIndentation(s => s.replace(/ /, '\t'));
assert.equal(Marker.toString(snippet.marker), 'foo\n bar');
assert.equal(Marker.toString(newSnippet.marker), 'foo\n\tbar');
snippet = SnippetParser.parse('foo\r\n bar\r\n far');
assert.equal(Marker.toString(snippet.marker), 'foo\r\n bar\r\n far');
snippet.adjustIndentation(s => s.replace(/ /, '\t'));
assert.equal(Marker.toString(snippet.marker), 'foo\r\n\tbar\r\n\tfar');
newSnippet = snippet.withIndentation(s => s.replace(/ /, '\t'));
assert.equal(Marker.toString(snippet.marker), 'foo\r\n bar\r\n far');
assert.equal(Marker.toString(newSnippet.marker), 'foo\r\n\tbar\r\n\tfar');
snippet = SnippetParser.parse('foo${1:bar\r far\r boo}');
assert.equal(Marker.toString(snippet.marker), 'foobar\r far\r boo');
snippet.adjustIndentation(s => s.replace(/ /, '\t'));
assert.equal(Marker.toString(snippet.marker), 'foobar\r\tfar\r\tboo');
newSnippet = snippet.withIndentation(s => s.replace(/ /, '\t'));
assert.equal(Marker.toString(snippet.marker), 'foobar\r far\r boo');
assert.equal(Marker.toString(newSnippet.marker), 'foobar\r\tfar\r\tboo');
});
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册