Skip to content

Commit

Permalink
Fix indentation after string literals containing escaped characters (#…
Browse files Browse the repository at this point in the history
…6440)

* Update indent regex
* Prettier formatting
* Add regex tests
* Undo prettier changes
* Forgot some
* One more
* Simplify & fix tests
* More descriptive comment
* Move language config to another file
* Remove unneeded tslint disable rule
  • Loading branch information
kimadeline authored Jul 8, 2019
1 parent 0eb059b commit d69efae
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 26 deletions.
1 change: 1 addition & 0 deletions news/2 Fixes/4241.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix indentation after string literals containing escaped characters.
29 changes: 3 additions & 26 deletions src/client/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {
Disposable,
ExtensionContext,
extensions,
IndentAction,
languages,
Memento,
OutputChannel,
Expand All @@ -41,7 +40,7 @@ import { registerTypes as appRegisterTypes } from './application/serviceRegistry
import { IApplicationDiagnostics } from './application/types';
import { DebugService } from './common/application/debugService';
import { IApplicationShell, ICommandManager, IWorkspaceService } from './common/application/types';
import { Commands, isTestExecution, PYTHON, PYTHON_LANGUAGE, STANDARD_OUTPUT_CHANNEL } from './common/constants';
import { Commands, isTestExecution, PYTHON, STANDARD_OUTPUT_CHANNEL } from './common/constants';
import { registerTypes as registerDotNetTypes } from './common/dotnet/serviceRegistry';
import { registerTypes as installerRegisterTypes } from './common/installer/serviceRegistry';
import { traceError } from './common/logger';
Expand Down Expand Up @@ -86,6 +85,7 @@ import { registerTypes as interpretersRegisterTypes } from './interpreter/servic
import { ServiceContainer } from './ioc/container';
import { ServiceManager } from './ioc/serviceManager';
import { IServiceContainer, IServiceManager } from './ioc/types';
import { setLanguageConfiguration } from './language/languageConfiguration';
import { LinterCommands } from './linters/linterCommands';
import { registerTypes as lintersRegisterTypes } from './linters/serviceRegistry';
import { ILintingEngine } from './linters/types';
Expand Down Expand Up @@ -173,30 +173,7 @@ async function activateUnsafe(context: ExtensionContext): Promise<IExtensionApi>
const linterProvider = new LinterProvider(context, serviceManager);
context.subscriptions.push(linterProvider);

// Enable indentAction
// tslint:disable-next-line:no-non-null-assertion
languages.setLanguageConfiguration(PYTHON_LANGUAGE, {
onEnterRules: [
{
beforeText: /^\s*(?:def|class|for|if|elif|else|while|try|with|finally|except|async)\b.*:\s*/,
action: { indentAction: IndentAction.Indent }
},
{
beforeText: /^(?!\s+\\)[^#\n]+\\\s*/,
action: { indentAction: IndentAction.Indent }
},
{
beforeText: /^\s*#.*/,
afterText: /.+$/,
action: { indentAction: IndentAction.None, appendText: '# ' }
},
{
beforeText: /^\s+(continue|break|return)\b.*/,
afterText: /\s+$/,
action: { indentAction: IndentAction.Outdent }
}
]
});
setLanguageConfiguration();

if (pythonSettings && pythonSettings.formatting && pythonSettings.formatting.provider !== 'internalConsole') {
const formatProvider = new PythonFormattingEditProvider(context, serviceContainer);
Expand Down
34 changes: 34 additions & 0 deletions src/client/language/languageConfiguration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
'use strict';

import { IndentAction, languages } from 'vscode';
import { PYTHON_LANGUAGE } from '../common/constants';

export const MULTILINE_SEPARATOR_INDENT_REGEX = /^(?!\s+\\)[^#\n]+\\$/;

export function setLanguageConfiguration() {
// Enable indentAction
languages.setLanguageConfiguration(PYTHON_LANGUAGE, {
onEnterRules: [
{
beforeText: /^\s*(?:def|class|for|if|elif|else|while|try|with|finally|except|async)\b.*:\s*/,
action: { indentAction: IndentAction.Indent }
},
{
beforeText: MULTILINE_SEPARATOR_INDENT_REGEX,
action: { indentAction: IndentAction.Indent }
},
{
beforeText: /^\s*#.*/,
afterText: /.+$/,
action: { indentAction: IndentAction.None, appendText: '# ' }
},
{
beforeText: /^\s+(continue|break|return)\b.*/,
afterText: /\s+$/,
action: { indentAction: IndentAction.Outdent }
}
]
});
}
23 changes: 23 additions & 0 deletions src/test/language/languageConfiguration.unit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

'use strict';

import { expect } from 'chai';

import { MULTILINE_SEPARATOR_INDENT_REGEX } from '../../client/language/languageConfiguration';

suite('Language configuration regexes', () => {
test('Multiline separator indent regex should not pick up strings with no multiline separator', async () => {
const result = MULTILINE_SEPARATOR_INDENT_REGEX.test('a = "test"');
expect (result).to.be.equal(false, 'Multiline separator indent regex for regular strings should not have matches');
});
test('Multiline separator indent regex should not pick up strings with escaped characters', async () => {
const result = MULTILINE_SEPARATOR_INDENT_REGEX.test('a = \'hello \\n\'');
expect (result).to.be.equal(false, 'Multiline separator indent regex for strings with escaped characters should not have matches');
});
test('Multiline separator indent regex should pick up strings ending with a multiline separator', async () => {
const result = MULTILINE_SEPARATOR_INDENT_REGEX.test('a = \'multiline \\');
expect (result).to.be.equal(true, 'Multiline separator indent regex for strings with newline separator should have matches');
});
});

0 comments on commit d69efae

Please sign in to comment.