Skip to content

Commit ec0ab31

Browse files
authored
Merge pull request microsoft#136579 from ssigwart/jsdoc2
Fix unwanted extra spaces when pasting code with JSDoc
2 parents 68dfc23 + 39911aa commit ec0ab31

File tree

4 files changed

+125
-23
lines changed

4 files changed

+125
-23
lines changed

src/vs/editor/common/languages/autoIndent.ts

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -228,33 +228,43 @@ export function getGoodIndentForLine(
228228
if (indent) {
229229
const inheritLine = indent.line;
230230
if (inheritLine !== undefined) {
231-
const enterResult = richEditSupport.onEnter(autoIndent, '', virtualModel.getLineContent(inheritLine), '');
231+
// Apply enter action as long as there are only whitespace lines between inherited line and this line.
232+
let shouldApplyEnterRules = true;
233+
for (let inBetweenLine = inheritLine; inBetweenLine < lineNumber - 1; inBetweenLine++) {
234+
if (!/^\s*$/.test(virtualModel.getLineContent(inBetweenLine))) {
235+
shouldApplyEnterRules = false;
236+
break;
237+
}
238+
}
239+
if (shouldApplyEnterRules) {
240+
const enterResult = richEditSupport.onEnter(autoIndent, '', virtualModel.getLineContent(inheritLine), '');
232241

233-
if (enterResult) {
234-
let indentation = strings.getLeadingWhitespace(virtualModel.getLineContent(inheritLine));
242+
if (enterResult) {
243+
let indentation = strings.getLeadingWhitespace(virtualModel.getLineContent(inheritLine));
235244

236-
if (enterResult.removeText) {
237-
indentation = indentation.substring(0, indentation.length - enterResult.removeText);
238-
}
245+
if (enterResult.removeText) {
246+
indentation = indentation.substring(0, indentation.length - enterResult.removeText);
247+
}
239248

240-
if (
241-
(enterResult.indentAction === IndentAction.Indent) ||
242-
(enterResult.indentAction === IndentAction.IndentOutdent)
243-
) {
244-
indentation = indentConverter.shiftIndent(indentation);
245-
} else if (enterResult.indentAction === IndentAction.Outdent) {
246-
indentation = indentConverter.unshiftIndent(indentation);
247-
}
249+
if (
250+
(enterResult.indentAction === IndentAction.Indent) ||
251+
(enterResult.indentAction === IndentAction.IndentOutdent)
252+
) {
253+
indentation = indentConverter.shiftIndent(indentation);
254+
} else if (enterResult.indentAction === IndentAction.Outdent) {
255+
indentation = indentConverter.unshiftIndent(indentation);
256+
}
248257

249-
if (indentRulesSupport.shouldDecrease(lineContent)) {
250-
indentation = indentConverter.unshiftIndent(indentation);
251-
}
258+
if (indentRulesSupport.shouldDecrease(lineContent)) {
259+
indentation = indentConverter.unshiftIndent(indentation);
260+
}
252261

253-
if (enterResult.appendText) {
254-
indentation += enterResult.appendText;
255-
}
262+
if (enterResult.appendText) {
263+
indentation += enterResult.appendText;
264+
}
256265

257-
return strings.getLeadingWhitespace(indentation);
266+
return strings.getLeadingWhitespace(indentation);
267+
}
258268
}
259269
}
260270

src/vs/editor/contrib/indentation/browser/indentation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ export class AutoIndentOnPaste implements IEditorContribution {
494494
}));
495495
}
496496

497-
private trigger(range: Range): void {
497+
public trigger(range: Range): void {
498498
const selections = this.editor.getSelections();
499499
if (selections === null || selections.length > 1) {
500500
return;

src/vs/editor/contrib/indentation/test/browser/indentation.test.ts

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,21 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import * as assert from 'assert';
67
import { Selection } from 'vs/editor/common/core/selection';
7-
import { IndentationToSpacesCommand, IndentationToTabsCommand } from 'vs/editor/contrib/indentation/browser/indentation';
8+
import { Range } from 'vs/editor/common/core/range';
9+
import { AutoIndentOnPaste, IndentationToSpacesCommand, IndentationToTabsCommand } from 'vs/editor/contrib/indentation/browser/indentation';
810
import { testCommand } from 'vs/editor/test/browser/testCommand';
11+
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
12+
import { javascriptIndentationRules } from 'vs/editor/test/common/modes/supports/javascriptIndentationRules';
13+
import { javascriptOnEnterRules } from 'vs/editor/test/common/modes/supports/javascriptOnEnterRules';
14+
import { DisposableStore } from 'vs/base/common/lifecycle';
15+
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
16+
import { ILanguageService } from 'vs/editor/common/languages/language';
17+
import { EncodedTokenizationResult, IState, TokenizationRegistry } from 'vs/editor/common/languages';
18+
import { MetadataConsts, StandardTokenType } from 'vs/editor/common/encodedTokenAttributes';
19+
import { createTextModel } from 'vs/editor/test/common/testTextModel';
20+
import { NullState } from 'vs/editor/common/languages/nullTokenize';
921

1022
function testIndentationToSpacesCommand(lines: string[], selection: Selection, tabSize: number, expectedLines: string[], expectedSelection: Selection): void {
1123
testCommand(lines, null, selection, (accessor, sel) => new IndentationToSpacesCommand(sel, tabSize), expectedLines, expectedSelection);
@@ -184,3 +196,72 @@ suite('Editor Contrib - Indentation to Tabs', () => {
184196
);
185197
});
186198
});
199+
200+
suite('Editor Contrib - Auto Indent On Paste', () => {
201+
let disposables: DisposableStore;
202+
203+
setup(() => {
204+
disposables = new DisposableStore();
205+
});
206+
207+
teardown(() => {
208+
disposables.dispose();
209+
});
210+
211+
test('issue #119225: Do not add extra leading space when pasting JSDoc', () => {
212+
const languageId = 'leadingSpacePaste';
213+
const model = createTextModel("", languageId, {});
214+
disposables.add(model);
215+
withTestCodeEditor(model, { autoIndent: 'full' }, (editor, viewModel, instantiationService) => {
216+
const languageService = instantiationService.get(ILanguageService);
217+
const languageConfigurationService = instantiationService.get(ILanguageConfigurationService);
218+
disposables.add(languageService.registerLanguage({ id: languageId }));
219+
disposables.add(TokenizationRegistry.register(languageId, {
220+
getInitialState: (): IState => NullState,
221+
tokenize: () => {
222+
throw new Error('not implemented');
223+
},
224+
tokenizeEncoded: (line: string, hasEOL: boolean, state: IState): EncodedTokenizationResult => {
225+
const tokensArr: number[] = [];
226+
if (line.indexOf('*') !== -1) {
227+
tokensArr.push(0);
228+
tokensArr.push(StandardTokenType.Comment << MetadataConsts.TOKEN_TYPE_OFFSET);
229+
} else {
230+
tokensArr.push(0);
231+
tokensArr.push(StandardTokenType.Other << MetadataConsts.TOKEN_TYPE_OFFSET);
232+
}
233+
const tokens = new Uint32Array(tokensArr.length);
234+
for (let i = 0; i < tokens.length; i++) {
235+
tokens[i] = tokensArr[i];
236+
}
237+
return new EncodedTokenizationResult(tokens, state);
238+
}
239+
}));
240+
disposables.add(languageConfigurationService.register(languageId, {
241+
brackets: [
242+
['{', '}'],
243+
['[', ']'],
244+
['(', ')']
245+
],
246+
comments: {
247+
lineComment: '//',
248+
blockComment: ['/*', '*/']
249+
},
250+
indentationRules: javascriptIndentationRules,
251+
onEnterRules: javascriptOnEnterRules
252+
}));
253+
254+
const autoIndentOnPasteController = editor.registerAndInstantiateContribution(AutoIndentOnPaste.ID, AutoIndentOnPaste);
255+
const pasteText = [
256+
'/**',
257+
' * JSDoc',
258+
' */',
259+
'function a() {}'
260+
].join('\n');
261+
262+
viewModel.paste(pasteText, true, undefined, 'keyboard');
263+
autoIndentOnPasteController.trigger(new Range(1, 1, 4, 16));
264+
assert.strictEqual(model.getValue(), pasteText);
265+
});
266+
});
267+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
export const javascriptIndentationRules = {
7+
decreaseIndentPattern: /^((?!.*?\/\*).*\*\/)?\s*[\}\]].*$/,
8+
increaseIndentPattern: /^((?!\/\/).)*(\{([^}"'`]*|(\t|[ ])*\/\/.*)|\([^)"'`]*|\[[^\]"'`]*)$/,
9+
// e.g. * ...| or */| or *-----*/|
10+
unIndentedLinePattern: /^(\t|[ ])*[ ]\*[^/]*\*\/\s*$|^(\t|[ ])*[ ]\*\/\s*$|^(\t|[ ])*[ ]\*([ ]([^\*]|\*(?!\/))*)?$/
11+
};

0 commit comments

Comments
 (0)