Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#840, #844 #848

Merged
merged 39 commits into from
Feb 21, 2018
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
6546892
Fix pylint search
Feb 16, 2018
76af122
Handle quote escapes in strings
Feb 16, 2018
5d4d022
Escapes in strings
Feb 16, 2018
29edac2
CR feedback
Feb 16, 2018
0492aab
Missing pip
Feb 17, 2018
d0a449f
Test
Feb 17, 2018
55197c3
Tests
Feb 17, 2018
f6a0123
Tests
Feb 17, 2018
d07d3ef
Mac python path
Feb 17, 2018
2b0cc92
Tests
Feb 17, 2018
3867ec2
Tests
Feb 17, 2018
85fc4ef
Test
Feb 17, 2018
00887a4
"Go To Python object" doesn't work
Feb 17, 2018
f89dd96
Proper detection and type population in virtual env
Feb 17, 2018
32394e2
Test fixes
Feb 17, 2018
2e9c039
Simplify venv check
Feb 17, 2018
ec563c7
Remove duplicates
Feb 17, 2018
2ad4475
Test
Feb 18, 2018
1ee0be2
Discover pylintrc better + tests
Feb 19, 2018
44665b9
Merge branch 'master' into 804
Feb 19, 2018
29d3925
Merge branch 'master' of https://github.com/Microsoft/vscode-python i…
Feb 19, 2018
04c5733
Undo change
Feb 19, 2018
37328a5
CR feedback
Feb 20, 2018
55ff4e5
Set interprereter before checking install
Feb 20, 2018
9a0cfa8
Merge master
Feb 20, 2018
023af49
Merge master
Feb 20, 2018
436e5a9
Fix typo and path compare on Windows
Feb 20, 2018
a53d815
Rename method
Feb 20, 2018
7f3e4fa
#815 - 'F' in flake8 means warning
Feb 20, 2018
da034f4
730 - same folder temp
Feb 20, 2018
71a508d
Properly resolve ~
Feb 20, 2018
4422811
Merge branch 'master' of https://github.com/Microsoft/vscode-python i…
Feb 20, 2018
6d91912
Test
Feb 21, 2018
ff6f6d2
Test
Feb 21, 2018
7446afb
Merge branch 'master' of https://github.com/Microsoft/vscode-python i…
Feb 21, 2018
a7b2854
Fix dot spacing
Feb 21, 2018
a9457f2
Merge branch 'master' of https://github.com/Microsoft/vscode-python i…
Feb 21, 2018
c7c07de
Remove banner
Feb 21, 2018
e9eec39
Delete banner code
Feb 21, 2018
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
6 changes: 4 additions & 2 deletions src/client/common/installer/pythonInstallation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ export class PythonInstaller {
return true;
}

await this.shell.showErrorMessage('Python is not installed. Please download and install Python before using the extension.');
this.shell.openUrl('https://www.python.org/downloads');
const download = 'Download';
if (await this.shell.showErrorMessage('Python is not installed. Please download and install Python before using the extension.', download) === download) {
this.shell.openUrl('https://www.python.org/downloads');
}
return false;
}
}
4 changes: 0 additions & 4 deletions src/client/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ if ((Reflect as any).metadata === undefined) {
import { Container } from 'inversify';
import * as vscode from 'vscode';
import { Disposable, Memento, OutputChannel, window } from 'vscode';
import { BannerService } from './banner';
import { PythonSettings } from './common/configSettings';
import * as settings from './common/configSettings';
import { STANDARD_OUTPUT_CHANNEL } from './common/constants';
Expand Down Expand Up @@ -183,9 +182,6 @@ export async function activate(context: vscode.ExtensionContext) {
});
activationDeferred.resolve();

// tslint:disable-next-line:no-unused-expression
new BannerService(persistentStateFactory);

const deprecationMgr = new FeatureDeprecationManager(persistentStateFactory, !!jupyterExtension);

Choose a reason for hiding this comment

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

We should delete the files related to BannerService

Copy link
Author

Choose a reason for hiding this comment

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

I thought we might need it to another banner just in case. But I guess it is easy to recover code from the history

deprecationMgr.initialize();
context.subscriptions.push(new FeatureDeprecationManager(persistentStateFactory, !!jupyterExtension));
Expand Down
42 changes: 31 additions & 11 deletions src/client/formatters/lineFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class LineFormatter {
break;

case TokenType.Identifier:
if (!prev || (!this.isOpenBraceType(prev.type) && prev.type !== TokenType.Colon)) {
if (prev && !this.isOpenBraceType(prev.type) && prev.type !== TokenType.Colon && prev.type !== TokenType.Operator) {
this.builder.softAppendSpace();
}
this.builder.append(this.text.substring(t.start, t.end));
Expand Down Expand Up @@ -81,24 +81,44 @@ export class LineFormatter {

private handleOperator(index: number): void {
const t = this.tokens.getItemAt(index);
if (index >= 2 && t.length === 1 && this.text.charCodeAt(t.start) === Char.Equal) {
if (this.braceCounter.isOpened(TokenType.OpenBrace)) {
// Check if this is = in function arguments. If so, do not
// add spaces around it.
const prev = this.tokens.getItemAt(index - 1);
const prevPrev = this.tokens.getItemAt(index - 2);
if (prev.type === TokenType.Identifier &&
(prevPrev.type === TokenType.Comma || prevPrev.type === TokenType.OpenBrace)) {
this.builder.append('=');
if (t.length === 1) {
const opCode = this.text.charCodeAt(t.start);
switch (opCode) {
case Char.Equal:
if (index >= 2 && this.handleEqual(t, index)) {
return;
}
break;
case Char.Period:
this.builder.append('.');
return;
case Char.At:
this.builder.append('@');
return;
}
default:
break;
}
}
this.builder.softAppendSpace();
this.builder.append(this.text.substring(t.start, t.end));
this.builder.softAppendSpace();
}

private handleEqual(t: IToken, index: number): boolean {
if (this.braceCounter.isOpened(TokenType.OpenBrace)) {
// Check if this is = in function arguments. If so, do not
// add spaces around it.
const prev = this.tokens.getItemAt(index - 1);
const prevPrev = this.tokens.getItemAt(index - 2);
if (prev.type === TokenType.Identifier &&
(prevPrev.type === TokenType.Comma || prevPrev.type === TokenType.OpenBrace)) {
this.builder.append('=');
return true;
}
}
return false;
}

private handleOther(t: IToken): void {
if (this.isBraceType(t.type)) {
this.braceCounter.countBrace(t);
Expand Down
4 changes: 2 additions & 2 deletions src/client/language/tokenizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ export class Tokenizer implements ITokenizer {
case Char.Colon:
this.tokens.push(new Token(TokenType.Colon, this.cs.position, 1));
break;
case Char.Period:
case Char.At:
this.tokens.push(new Token(TokenType.Unknown, this.cs.position, 1));
case Char.Period:
this.tokens.push(new Token(TokenType.Operator, this.cs.position, 1));
break;
default:
if (this.isPossibleNumber()) {
Expand Down
49 changes: 33 additions & 16 deletions src/test/format/extension.onEnterFormat.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,47 +12,64 @@ const unformattedFile = path.join(formatFilesPath, 'fileToFormatOnEnter.py');

suite('Formatting - OnEnter provider', () => {
let document: vscode.TextDocument;
let editor: vscode.TextEditor;

suiteSetup(initialize);
setup(async () => {
document = await vscode.workspace.openTextDocument(unformattedFile);
await vscode.window.showTextDocument(document);
editor = await vscode.window.showTextDocument(document);
});
suiteTeardown(closeActiveWindows);
teardown(closeActiveWindows);

test('Regular string', async () => {
const edits = await formatAtPosition(1, 0);
assert.notEqual(edits!.length, 0, 'Line was not formatted');
test('Simple statement', async () => {
const text = await formatAtPosition(1, 0);
assert.equal(text, 'x = 1', 'Line was not formatted');
});

test('No formatting inside strings', async () => {
const edits = await formatAtPosition(2, 0);
assert.equal(edits!.length, 0, 'Text inside string was formatted');
let text = await formatAtPosition(2, 0);
assert.equal(text, '"""x=1', 'Text inside string was formatted');
text = await formatAtPosition(3, 0);
assert.equal(text, '"""', 'Text inside string was formatted');
});

test('Whitespace before comment', async () => {
const edits = await formatAtPosition(4, 0);
assert.equal(edits!.length, 0, 'Whitespace before comment was formatted');
const text = await formatAtPosition(4, 0);
assert.equal(text, ' # comment', 'Whitespace before comment was not preserved');
});

test('No formatting of comment', async () => {
const edits = await formatAtPosition(5, 0);
assert.equal(edits!.length, 0, 'Text inside comment was formatted');
const text = await formatAtPosition(5, 0);
assert.equal(text, '# x=1', 'Text inside comment was formatted');
});

test('Formatting line ending in comment', async () => {
const edits = await formatAtPosition(6, 0);
assert.notEqual(edits!.length, 0, 'Line ending in comment was not formatted');
const text = await formatAtPosition(6, 0);
assert.equal(text, 'x + 1 # ', 'Line ending in comment was not formatted');
});

test('Formatting line with @', async () => {
const text = await formatAtPosition(7, 0);
assert.equal(text, '@x', 'Line with @ was reformatted');
});

test('Formatting line with @', async () => {
const text = await formatAtPosition(8, 0);
assert.equal(text, 'x.y', 'Line ending with period was reformatted');
});

test('Formatting line ending in string', async () => {
const edits = await formatAtPosition(7, 0);
assert.notEqual(edits!.length, 0, 'Line ending in multilint string was not formatted');
const text = await formatAtPosition(9, 0);
assert.equal(text, 'x + """', 'Line ending in multiline string was not formatted');
});

async function formatAtPosition(line: number, character: number): Promise<vscode.TextEdit[] | undefined> {
return await vscode.commands.executeCommand<vscode.TextEdit[]>('vscode.executeFormatOnTypeProvider',
async function formatAtPosition(line: number, character: number): Promise<string> {
const edits = await vscode.commands.executeCommand<vscode.TextEdit[]>('vscode.executeFormatOnTypeProvider',
document.uri, new vscode.Position(line, character), '\n', { insertSpaces: true, tabSize: 2 });
if (edits) {
await editor.edit(builder => edits.forEach(e => builder.replace(e.range, e.newText)));
}
return document.lineAt(line - 1).text;
}
});
17 changes: 16 additions & 1 deletion src/test/install/pythonInstallation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ suite('Installation', () => {
let openUrlCalled = false;
let url;

c.appShell.setup(x => x.showErrorMessage(TypeMoq.It.isAnyString())).callback(() => showErrorMessageCalled = true);
const download = 'Download';
c.appShell
.setup(x => x.showErrorMessage(TypeMoq.It.isAnyString(), download))
.callback(() => showErrorMessageCalled = true)
.returns(() => Promise.resolve(download));
c.appShell.setup(x => x.openUrl(TypeMoq.It.isAnyString())).callback((s: string) => {
openUrlCalled = true;
url = s;
Expand All @@ -93,6 +97,17 @@ suite('Installation', () => {
assert.equal(showErrorMessageCalled, true, 'Error message not shown');
assert.equal(openUrlCalled, true, 'Python download page not opened');
assert.equal(url, 'https://www.python.org/downloads', 'Python download page is incorrect');

showErrorMessageCalled = false;
openUrlCalled = false;
c.appShell
.setup(x => x.showErrorMessage(TypeMoq.It.isAnyString(), download))
.callback(() => showErrorMessageCalled = true)
.returns(() => Promise.resolve(''));

await c.pythonInstaller.checkPythonInstallation(c.settings.object);
assert.equal(showErrorMessageCalled, true, 'Error message not shown');
assert.equal(openUrlCalled, false, 'Python download page was opened');
});

test('Mac: Default Python warning', async () => {
Expand Down
16 changes: 12 additions & 4 deletions src/test/language/tokenizer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,23 @@ suite('Language.Tokenizer', () => {
assert.equal(tokens.getItemAt(i).type, TokenType.Comment);
}
});
test('Period/At to unknown token', async () => {
test('Period to operator token', async () => {
const t = new Tokenizer();
const tokens = t.tokenize('.@x');
const tokens = t.tokenize('x.y');
assert.equal(tokens.count, 3);

assert.equal(tokens.getItemAt(0).type, TokenType.Unknown);
assert.equal(tokens.getItemAt(1).type, TokenType.Unknown);
assert.equal(tokens.getItemAt(0).type, TokenType.Identifier);
assert.equal(tokens.getItemAt(1).type, TokenType.Operator);
assert.equal(tokens.getItemAt(2).type, TokenType.Identifier);
});
test('@ to operator token', async () => {
const t = new Tokenizer();
const tokens = t.tokenize('@x');
assert.equal(tokens.count, 2);

assert.equal(tokens.getItemAt(0).type, TokenType.Operator);
assert.equal(tokens.getItemAt(1).type, TokenType.Identifier);
});
test('Unknown token', async () => {
const t = new Tokenizer();
const tokens = t.tokenize('~$');
Expand Down
2 changes: 2 additions & 0 deletions src/test/pythonFiles/formatting/fileToFormatOnEnter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@
# comment
# x=1
x+1 #
@x
x.y
x+"""