mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Merge from vscode 3d67364fbfcf676d93be64f949e9b33e7f1b969e (#5028)
This commit is contained in:
@@ -1031,7 +1031,7 @@
|
||||
],
|
||||
"markdownDescription": "%config.path%",
|
||||
"default": null,
|
||||
"scope": "application"
|
||||
"scope": "machine"
|
||||
},
|
||||
"git.autoRepositoryDetection": {
|
||||
"type": [
|
||||
|
||||
@@ -381,7 +381,14 @@ export class MarkdownPreview extends Disposable {
|
||||
clearTimeout(this.throttleTimer);
|
||||
this.throttleTimer = undefined;
|
||||
|
||||
const document = await vscode.workspace.openTextDocument(resource);
|
||||
let document: vscode.TextDocument;
|
||||
try {
|
||||
document = await vscode.workspace.openTextDocument(resource);
|
||||
} catch {
|
||||
await this.showFileNotFoundError();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.forceUpdate && this.currentVersion && this.currentVersion.resource.fsPath === resource.fsPath && this.currentVersion.version === document.version) {
|
||||
if (this.line) {
|
||||
this.updateForView(resource, this.line);
|
||||
@@ -391,12 +398,9 @@ export class MarkdownPreview extends Disposable {
|
||||
this.forceUpdate = false;
|
||||
|
||||
this.currentVersion = { resource, version: document.version };
|
||||
const content = await this._contentProvider.provideTextDocumentContent(document, this._previewConfigurations, this.line, this.state);
|
||||
if (this._resource === resource) {
|
||||
this.editor.title = MarkdownPreview.getPreviewTitle(this._resource, this._locked);
|
||||
this.editor.iconPath = this.iconPath;
|
||||
this.editor.webview.options = MarkdownPreview.getWebviewOptions(resource, this._contributionProvider.contributions);
|
||||
this.editor.webview.html = content;
|
||||
const content = await this._contentProvider.provideTextDocumentContent(document, this._previewConfigurations, this.line, this.state);
|
||||
this.setContent(content);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,7 +460,22 @@ export class MarkdownPreview extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
vscode.workspace.openTextDocument(this._resource).then(vscode.window.showTextDocument);
|
||||
vscode.workspace.openTextDocument(this._resource)
|
||||
.then(vscode.window.showTextDocument)
|
||||
.then(undefined, () => {
|
||||
vscode.window.showErrorMessage(localize('preview.clickOpenFailed', 'Could not open {0}', this._resource.toString()));
|
||||
});
|
||||
}
|
||||
|
||||
private async showFileNotFoundError() {
|
||||
this.setContent(this._contentProvider.provideFileNotFoundContent(this._resource));
|
||||
}
|
||||
|
||||
private setContent(html: string): void {
|
||||
this.editor.title = MarkdownPreview.getPreviewTitle(this._resource, this._locked);
|
||||
this.editor.iconPath = this.iconPath;
|
||||
this.editor.webview.options = MarkdownPreview.getWebviewOptions(this._resource, this._contributionProvider.contributions);
|
||||
this.editor.webview.html = html;
|
||||
}
|
||||
|
||||
private async onDidClickPreviewLink(path: string, fragment: string | undefined) {
|
||||
|
||||
@@ -90,6 +90,19 @@ export class MarkdownContentProvider {
|
||||
</html>`;
|
||||
}
|
||||
|
||||
public provideFileNotFoundContent(
|
||||
resource: vscode.Uri,
|
||||
): string {
|
||||
const resourcePath = path.basename(resource.fsPath);
|
||||
const body = localize('preview.notFound', '{0} cannot be found', resourcePath);
|
||||
return `<!DOCTYPE html>
|
||||
<html>
|
||||
<body class="vscode-body">
|
||||
${body}
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
private extensionResourcePath(mediaFile: string): string {
|
||||
return vscode.Uri.file(this.context.asAbsolutePath(path.join('media', mediaFile)))
|
||||
.with({ scheme: 'vscode-resource' })
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"version": "0.0.1",
|
||||
"description": "Dependencies shared by all extensions",
|
||||
"dependencies": {
|
||||
"typescript": "3.4.3-insiders.20190408"
|
||||
"typescript": "3.4.3"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "node ./postinstall"
|
||||
|
||||
@@ -68,7 +68,12 @@
|
||||
},
|
||||
{
|
||||
"name": "Control flow keywords",
|
||||
"scope": "keyword.control",
|
||||
"scope": [
|
||||
"keyword.control",
|
||||
"keyword.operator.new.cpp",
|
||||
"keyword.operator.delete.cpp",
|
||||
"keyword.other.using"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#C586C0"
|
||||
}
|
||||
|
||||
@@ -65,7 +65,12 @@
|
||||
},
|
||||
{
|
||||
"name": "Control flow keywords",
|
||||
"scope": "keyword.control",
|
||||
"scope": [
|
||||
"keyword.control",
|
||||
"keyword.operator.new.cpp",
|
||||
"keyword.operator.delete.cpp",
|
||||
"keyword.other.using"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#C586C0"
|
||||
}
|
||||
|
||||
@@ -68,7 +68,12 @@
|
||||
},
|
||||
{
|
||||
"name": "Control flow keywords",
|
||||
"scope": "keyword.control",
|
||||
"scope": [
|
||||
"keyword.control",
|
||||
"keyword.operator.new.cpp",
|
||||
"keyword.operator.delete.cpp",
|
||||
"keyword.other.using"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#AF00DB"
|
||||
}
|
||||
|
||||
@@ -113,7 +113,10 @@
|
||||
"name": "Keywords",
|
||||
"scope": [
|
||||
"keyword",
|
||||
"keyword.control"
|
||||
"keyword.control",
|
||||
"keyword.operator.new.cpp",
|
||||
"keyword.operator.delete.cpp",
|
||||
"keyword.other.using"
|
||||
],
|
||||
"settings": {
|
||||
"foreground": "#98676a"
|
||||
|
||||
@@ -255,7 +255,12 @@
|
||||
},
|
||||
{
|
||||
"name": "Keyword Control",
|
||||
"scope": "keyword.control",
|
||||
"scope": [
|
||||
"keyword.control",
|
||||
"keyword.operator.new.cpp",
|
||||
"keyword.operator.delete.cpp",
|
||||
"keyword.other.using"
|
||||
],
|
||||
"settings": {
|
||||
"fontStyle": "",
|
||||
"foreground": "#9872A2"
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as Proto from '../protocol';
|
||||
import { ITypeScriptServiceClient } from '../typescriptService';
|
||||
import API from '../utils/api';
|
||||
import { VersionDependentRegistration } from '../utils/dependentRegistration';
|
||||
import * as typeConverters from '../utils/typeConverters';
|
||||
|
||||
class SmartSelection implements vscode.SelectionRangeProvider {
|
||||
public static readonly minVersion = API.v350;
|
||||
|
||||
public constructor(
|
||||
private readonly client: ITypeScriptServiceClient
|
||||
) { }
|
||||
|
||||
public async provideSelectionRanges(
|
||||
document: vscode.TextDocument,
|
||||
positions: vscode.Position[],
|
||||
token: vscode.CancellationToken,
|
||||
): Promise<vscode.SelectionRange[] | undefined> {
|
||||
const file = this.client.toOpenedFilePath(document);
|
||||
if (!file) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const args: Proto.FileRequestArgs & { locations: Proto.Location[] } = {
|
||||
file,
|
||||
locations: positions.map(typeConverters.Position.toLocation)
|
||||
};
|
||||
const response = await this.client.execute('selectionRange', args, token);
|
||||
if (response.type !== 'response' || !response.body) {
|
||||
return undefined;
|
||||
}
|
||||
return response.body.map(SmartSelection.convertSelectionRange);
|
||||
}
|
||||
|
||||
private static convertSelectionRange(
|
||||
selectionRange: Proto.SelectionRange
|
||||
): vscode.SelectionRange {
|
||||
return new vscode.SelectionRange(
|
||||
typeConverters.Range.fromTextSpan(selectionRange.textSpan),
|
||||
selectionRange.parent ? SmartSelection.convertSelectionRange(selectionRange.parent) : undefined,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function register(
|
||||
selector: vscode.DocumentSelector,
|
||||
client: ITypeScriptServiceClient,
|
||||
) {
|
||||
return new VersionDependentRegistration(client, SmartSelection.minVersion, () =>
|
||||
vscode.languages.registerSelectionRangeProvider(selector, new SmartSelection(client)));
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import 'mocha';
|
||||
import * as vscode from 'vscode';
|
||||
import { CURSOR, withRandomFileEditor } from './testUtils';
|
||||
|
||||
const onDocumentChange = (doc: vscode.TextDocument): Promise<vscode.TextDocument> => {
|
||||
return new Promise<vscode.TextDocument>(resolve => {
|
||||
const sub = vscode.workspace.onDidChangeTextDocument(e => {
|
||||
if (e.document !== doc) {
|
||||
return;
|
||||
}
|
||||
sub.dispose();
|
||||
resolve(e.document);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const type = async (document: vscode.TextDocument, text: string): Promise<vscode.TextDocument> => {
|
||||
const onChange = onDocumentChange(document);
|
||||
await vscode.commands.executeCommand('type', { text });
|
||||
await onChange;
|
||||
return document;
|
||||
};
|
||||
|
||||
suite('OnEnter', () => {
|
||||
test('should indent after if block with braces', () => {
|
||||
return withRandomFileEditor(`if (true) {${CURSOR}`, 'js', async (_editor, document) => {
|
||||
await type(document, '\nx');
|
||||
assert.strictEqual(document.getText(), `if (true) {\n x`);
|
||||
});
|
||||
});
|
||||
|
||||
test('should indent within empty object literal', () => {
|
||||
return withRandomFileEditor(`({${CURSOR}})`, 'js', async (_editor, document) => {
|
||||
await type(document, '\nx');
|
||||
assert.strictEqual(document.getText(), `({\n x\n})`);
|
||||
});
|
||||
});
|
||||
|
||||
test('should indent after simple jsx tag with attributes', () => {
|
||||
return withRandomFileEditor(`const a = <div onclick={bla}>${CURSOR}`, 'jsx', async (_editor, document) => {
|
||||
await type(document, '\nx');
|
||||
assert.strictEqual(document.getText(), `const a = <div onclick={bla}>\n x`);
|
||||
});
|
||||
});
|
||||
|
||||
test('should indent after simple jsx tag with attributes', () => {
|
||||
return withRandomFileEditor(`const a = <div onclick={bla}>${CURSOR}`, 'jsx', async (_editor, document) => {
|
||||
await type(document, '\nx');
|
||||
assert.strictEqual(document.getText(), `const a = <div onclick={bla}>\n x`);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,68 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import { join } from 'path';
|
||||
|
||||
function rndName() {
|
||||
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10);
|
||||
}
|
||||
|
||||
export function createRandomFile(contents = '', fileExtension = 'txt'): Thenable<vscode.Uri> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const tmpFile = join(os.tmpdir(), rndName() + '.' + fileExtension);
|
||||
fs.writeFile(tmpFile, contents, (error) => {
|
||||
if (error) {
|
||||
return reject(error);
|
||||
}
|
||||
|
||||
resolve(vscode.Uri.file(tmpFile));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function deleteFile(file: vscode.Uri): Thenable<boolean> {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.unlink(file.fsPath, (err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export const CURSOR = '$$CURSOR$$';
|
||||
|
||||
export function withRandomFileEditor(
|
||||
contents: string,
|
||||
fileExtension: string,
|
||||
run: (editor: vscode.TextEditor, doc: vscode.TextDocument) => Thenable<void>
|
||||
): Thenable<boolean> {
|
||||
const cursorIndex = contents.indexOf(CURSOR);
|
||||
return createRandomFile(contents.replace(CURSOR, ''), fileExtension).then(file => {
|
||||
return vscode.workspace.openTextDocument(file).then(doc => {
|
||||
return vscode.window.showTextDocument(doc).then((editor) => {
|
||||
if (cursorIndex >= 0) {
|
||||
const pos = doc.positionAt(cursorIndex);
|
||||
editor.selection = new vscode.Selection(pos, pos);
|
||||
}
|
||||
return run(editor, doc).then(_ => {
|
||||
if (doc.isDirty) {
|
||||
return doc.save().then(() => {
|
||||
return deleteFile(file);
|
||||
});
|
||||
} else {
|
||||
return deleteFile(file);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
typescript@3.4.3-insiders.20190408:
|
||||
version "3.4.3-insiders.20190408"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.3-insiders.20190408.tgz#18d98336c693a13dc8b2d5f39b70268c018c650b"
|
||||
integrity sha512-5SI6EA+2u0ea/Uy0qCEczh8vBR0ByVaCFCyU0RdROROw8V5O4OIQHMFcnIdyg+nnfRGYp39PxvllGMDpsTFOOQ==
|
||||
typescript@3.4.3:
|
||||
version "3.4.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.3.tgz#0eb320e4ace9b10eadf5bc6103286b0f8b7c224f"
|
||||
integrity sha512-FFgHdPt4T/duxx6Ndf7hwgMZZjZpB+U0nMNGVCYPq0rEzWKjEDobm4J6yb3CS7naZ0yURFqdw9Gwc7UOh/P9oQ==
|
||||
|
||||
Reference in New Issue
Block a user