Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/client/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,8 @@ export function isTestExecution(): boolean {
// tslint:disable-next-line:interface-name no-string-literal
return process.env['VSC_PYTHON_CI_TEST'] === '1';
}
export function isPythonAnalysisEngineTest(): boolean {
return process.env.VSC_PYTHON_ANALYSIS === '1';
}

export const EXTENSION_ROOT_DIR = path.join(__dirname, '..', '..', '..');
11 changes: 7 additions & 4 deletions src/client/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@ import {
extensions, IndentAction, languages, Memento,
OutputChannel, window
} from 'vscode';
import { IS_ANALYSIS_ENGINE_TEST } from '../test/constants';
import { AnalysisExtensionActivator } from './activation/analysis';
import { ClassicExtensionActivator } from './activation/classic';
import { IExtensionActivator } from './activation/types';
import { PythonSettings } from './common/configSettings';
import { STANDARD_OUTPUT_CHANNEL } from './common/constants';
import { isPythonAnalysisEngineTest, STANDARD_OUTPUT_CHANNEL } from './common/constants';
import { FeatureDeprecationManager } from './common/featureDeprecationManager';
import { createDeferred } from './common/helpers';
import { PythonInstaller } from './common/installer/pythonInstallation';
Expand Down Expand Up @@ -75,7 +74,7 @@ export async function activate(context: ExtensionContext) {
const configuration = serviceManager.get<IConfigurationService>(IConfigurationService);
const pythonSettings = configuration.getSettings();

const activator: IExtensionActivator = IS_ANALYSIS_ENGINE_TEST || !pythonSettings.jediEnabled
const activator: IExtensionActivator = isPythonAnalysisEngineTest() || !pythonSettings.jediEnabled
? new AnalysisExtensionActivator(serviceManager, pythonSettings)
: new ClassicExtensionActivator(serviceManager, pythonSettings);

Expand Down Expand Up @@ -108,7 +107,11 @@ export async function activate(context: ExtensionContext) {
languages.setLanguageConfiguration(PYTHON.language!, {
onEnterRules: [
{
beforeText: /^\s*(?:def|class|for|if|elif|else|while|try|with|finally|except|async)\b.*/,
beforeText: /^\s*(?:def|class|for|if|elif|else|while|try|with|finally|except)\b.*:\s*\S+/,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've created an issue (#1314) to ensure we try (some how) create tests to test this indentation. We've had to make changes to this area a number of times.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, yet to figure out how to simulate typing in VSC.

action: { indentAction: IndentAction.None }
},
{
beforeText: /^\s*(?:def|class|for|if|elif|else|while|try|with|finally|except|async)\b.*:\s*/,
action: { indentAction: IndentAction.Indent }
},
{
Expand Down
13 changes: 10 additions & 3 deletions src/client/formatters/lineFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,22 @@ export class LineFormatter {
}
break;
case Char.Period:
this.builder.append('.');
return;
case Char.At:
this.builder.append('@');
case Char.ExclamationMark:
this.builder.append(this.text[t.start]);
return;
default:
break;
}
}
// Do not append space if operator is preceded by '(' or ',' as in foo(**kwarg)
if (index > 0) {
const prev = this.tokens.getItemAt(index - 1);
if (this.isOpenBraceType(prev.type) || prev.type === TokenType.Comma) {
this.builder.append(this.text.substring(t.start, t.end));
return;
}
}
this.builder.softAppendSpace();
this.builder.append(this.text.substring(t.start, t.end));
this.builder.softAppendSpace();
Expand Down
12 changes: 9 additions & 3 deletions src/client/language/tokenizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,16 @@ export class Tokenizer implements ITokenizer {
}
}

// tslint:disable-next-line:cyclomatic-complexity
private handleCharacter(): boolean {
// f-strings
const fString = this.cs.currentChar === Char.f && (this.cs.nextChar === Char.SingleQuote || this.cs.nextChar === Char.DoubleQuote);
if (fString) {
this.cs.moveNext();
}
const quoteType = this.getQuoteType();
if (quoteType !== QuoteType.None) {
this.handleString(quoteType);
this.handleString(quoteType, fString);
return true;
}
if (this.cs.currentChar === Char.Hash) {
Expand Down Expand Up @@ -342,8 +348,8 @@ export class Tokenizer implements ITokenizer {
return QuoteType.None;
}

private handleString(quoteType: QuoteType): void {
const start = this.cs.position;
private handleString(quoteType: QuoteType, fString: boolean): void {
const start = fString ? this.cs.position - 1 : this.cs.position;
if (quoteType === QuoteType.Single || quoteType === QuoteType.Double) {
this.cs.moveNext();
this.skipToSingleEndQuote(quoteType === QuoteType.Single
Expand Down
6 changes: 5 additions & 1 deletion src/test/format/extension.lineFormatter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,16 @@ suite('Formatting - line formatter', () => {
const actual = formatter.formatLine('foo(x,y= \"a\",');
assert.equal(actual, 'foo(x, y=\"a\",');
});
test('Equals in multiline arguments', () => {
test('Equals in multiline arguments', () => {
const actual = formatter.formatLine('x = 1,y =-2)');
assert.equal(actual, 'x=1, y=-2)');
});
test('Equals in multiline arguments starting comma', () => {
const actual = formatter.formatLine(',x = 1,y =m)');
assert.equal(actual, ', x=1, y=m)');
});
test('Operators without following space', () => {
const actual = formatter.formatLine('foo( *a, ** b, ! c)');
assert.equal(actual, 'foo(*a, **b, !c)');
});
});
37 changes: 37 additions & 0 deletions src/test/language/tokenizer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,43 @@ suite('Language.Tokenizer', () => {
assert.equal(tokens.getItemAt(0).type, TokenType.String);
assert.equal(tokens.getItemAt(0).length, 12);
});
test('Strings: single quoted f-string ', async () => {
const t = new Tokenizer();
// tslint:disable-next-line:quotemark
const tokens = t.tokenize("a+f'quoted'");
assert.equal(tokens.count, 3);
assert.equal(tokens.getItemAt(0).type, TokenType.Identifier);
assert.equal(tokens.getItemAt(1).type, TokenType.Operator);
assert.equal(tokens.getItemAt(2).type, TokenType.String);
assert.equal(tokens.getItemAt(2).length, 9);
});
test('Strings: double quoted f-string ', async () => {
const t = new Tokenizer();
const tokens = t.tokenize('x(1,f"quoted")');
assert.equal(tokens.count, 6);
assert.equal(tokens.getItemAt(0).type, TokenType.Identifier);
assert.equal(tokens.getItemAt(1).type, TokenType.OpenBrace);
assert.equal(tokens.getItemAt(2).type, TokenType.Number);
assert.equal(tokens.getItemAt(3).type, TokenType.Comma);
assert.equal(tokens.getItemAt(4).type, TokenType.String);
assert.equal(tokens.getItemAt(4).length, 9);
assert.equal(tokens.getItemAt(5).type, TokenType.CloseBrace);
});
test('Strings: single quoted multiline f-string ', async () => {
const t = new Tokenizer();
// tslint:disable-next-line:quotemark
const tokens = t.tokenize("f'''quoted'''");
assert.equal(tokens.count, 1);
assert.equal(tokens.getItemAt(0).type, TokenType.String);
assert.equal(tokens.getItemAt(0).length, 13);
});
test('Strings: double quoted multiline f-string ', async () => {
const t = new Tokenizer();
const tokens = t.tokenize('f"""quoted """');
assert.equal(tokens.count, 1);
assert.equal(tokens.getItemAt(0).type, TokenType.String);
assert.equal(tokens.getItemAt(0).length, 14);
});
test('Comments', async () => {
const t = new Tokenizer();
const tokens = t.tokenize(' #co"""mment1\n\t\n#comm\'ent2 ');
Expand Down