diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index bcc36817b4..96d70c65da 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -46,7 +46,6 @@ expressly granted herein, whether by implication, estoppel or otherwise. node-fetch: https://github.com/bitinn/node-fetch node-pty: https://github.com/Tyriar/node-pty nsfw: https://github.com/Axosoft/nsfw - pretty-data: https://github.com/vkiryukhin/pretty-data primeng: https://github.com/primefaces/primeng process-nextick-args: https://github.com/calvinmetcalf/process-nextick-args pty.js: https://github.com/chjj/pty.js @@ -1420,16 +1419,6 @@ SOFTWARE. ========================================= END OF nsfw NOTICES AND INFORMATION -%% pretty-data NOTICES AND INFORMATION BEGIN HERE -========================================= -License: Dual licensed under the MIT and GPL licenses: - -http://www.opensource.org/licenses/mit-license.php - -http://www.gnu.org/licenses/gpl.html -========================================= -END OF pretty-data NOTICES AND INFORMATION - %% primeng NOTICES AND INFORMATION BEGIN HERE ========================================= The MIT License (MIT) diff --git a/extensions/xml-language-features/.vscodeignore b/extensions/xml-language-features/.vscodeignore new file mode 100644 index 0000000000..30d948fbc6 --- /dev/null +++ b/extensions/xml-language-features/.vscodeignore @@ -0,0 +1,10 @@ +test/** +src/** +tsconfig.json +out/test/** +out/** +extension.webpack.config.js +cgmanifest.json +yarn.lock +preview-src/** +webpack.config.js diff --git a/extensions/xml-language-features/extension.webpack.config.js b/extensions/xml-language-features/extension.webpack.config.js new file mode 100644 index 0000000000..f35561d9f2 --- /dev/null +++ b/extensions/xml-language-features/extension.webpack.config.js @@ -0,0 +1,20 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +//@ts-check + +'use strict'; + +const withDefaults = require('../shared.webpack.config'); + +module.exports = withDefaults({ + context: __dirname, + resolve: { + mainFields: ['module', 'main'] + }, + entry: { + extension: './src/extension.ts', + } +}); diff --git a/extensions/xml-language-features/package.json b/extensions/xml-language-features/package.json new file mode 100644 index 0000000000..a715472e47 --- /dev/null +++ b/extensions/xml-language-features/package.json @@ -0,0 +1,27 @@ +{ + "name": "xml-language-features", + "displayName": "%displayName%", + "description": "%description%", + "version": "1.0.0", + "publisher": "microsoft", + "engines": { + "vscode": "^1.20.0" + }, + "main": "./out/extension", + "categories": [ + "Programming Languages" + ], + "activationEvents": [ + "onLanguage:xml" + ], + "scripts": { + "compile": "gulp compile-extension:markdown-language-features && npm run build-preview", + "watch": "npm run build-preview && gulp watch-extension:markdown-language-features", + "vscode:prepublish": "npm run build-ext && npm run build-preview", + "build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:markdown-language-features ./tsconfig.json", + "build-preview": "webpack --mode development" + }, + "dependencies": { + "tsxml": "^0.1.0" + } +} diff --git a/extensions/xml-language-features/package.nls.json b/extensions/xml-language-features/package.nls.json new file mode 100644 index 0000000000..0021e0b113 --- /dev/null +++ b/extensions/xml-language-features/package.nls.json @@ -0,0 +1,4 @@ +{ + "displayName": "XML Language Features", + "description": "Provides rich language support for XML." +} diff --git a/extensions/xml-language-features/src/extension.ts b/extensions/xml-language-features/src/extension.ts new file mode 100644 index 0000000000..603b3bb37c --- /dev/null +++ b/extensions/xml-language-features/src/extension.ts @@ -0,0 +1,18 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import * as xml from 'tsxml'; + +export function activate(context: vscode.ExtensionContext) { + context.subscriptions.push(vscode.languages.registerDocumentFormattingEditProvider({ language: 'xml' }, { + provideDocumentFormattingEdits: document => format(document) + })); +} + +function format(document: vscode.TextDocument): vscode.ProviderResult { + const range = new vscode.Range(0, 0, document.lineCount, document.lineAt(document.lineCount - 1).range.end.character); + return xml.Compiler.formatXmlString(document.getText()).then(formatted => [new vscode.TextEdit(range, formatted)]); +} diff --git a/src/typings/prettyData.d.ts b/extensions/xml-language-features/src/typings/refs.d.ts similarity index 73% rename from src/typings/prettyData.d.ts rename to extensions/xml-language-features/src/typings/refs.d.ts index 87c3d1e114..4912c31c1a 100644 --- a/src/typings/prettyData.d.ts +++ b/extensions/xml-language-features/src/typings/refs.d.ts @@ -3,9 +3,5 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -declare module 'pretty-data' { - export interface PrettyData { - xml(input: string): string; - } - export var pd: PrettyData; -} +/// +/// \ No newline at end of file diff --git a/extensions/xml-language-features/tsconfig.json b/extensions/xml-language-features/tsconfig.json new file mode 100644 index 0000000000..27e9268b39 --- /dev/null +++ b/extensions/xml-language-features/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../shared.tsconfig.json", + "compilerOptions": { + "outDir": "./out", + "experimentalDecorators": true, + "typeRoots": [ + "./node_modules/@types" + ] + }, + "include": [ + "src/**/*" + ] +} \ No newline at end of file diff --git a/extensions/xml-language-features/yarn.lock b/extensions/xml-language-features/yarn.lock new file mode 100644 index 0000000000..cf7e370ca0 --- /dev/null +++ b/extensions/xml-language-features/yarn.lock @@ -0,0 +1,8 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +tsxml@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/tsxml/-/tsxml-0.1.0.tgz#d73f14a0d844af51edc0b98bdb52634a41b9b0d4" + integrity sha1-1z8UoNhEr1HtwLmL21JjSkG5sNQ= diff --git a/package.json b/package.json index fcbb6be98c..1c630d5ae2 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,6 @@ "native-watchdog": "1.0.0", "ng2-charts": "^1.6.0", "node-pty": "0.9.0-beta9", - "pretty-data": "^0.40.0", "reflect-metadata": "^0.1.8", "rxjs": "5.4.0", "sanitize-html": "^1.19.1", diff --git a/src/bootstrap-window.js b/src/bootstrap-window.js index 32303e3c43..b1d54acd3c 100644 --- a/src/bootstrap-window.js +++ b/src/bootstrap-window.js @@ -115,7 +115,6 @@ exports.load = function (modulePaths, resultCallback, options) { '@angular/router', 'angular2-grid', 'ansi_up', - 'pretty-data', 'html-query-plan', 'ng2-charts', 'rxjs/Observable', diff --git a/src/sql/platform/node/resultSerializer.ts b/src/sql/platform/node/resultSerializer.ts index f98659520b..1817ac173e 100644 --- a/src/sql/platform/node/resultSerializer.ts +++ b/src/sql/platform/node/resultSerializer.ts @@ -11,16 +11,12 @@ import { SaveResultsRequestParams } from 'azdata'; import { IQueryManagementService } from 'sql/platform/query/common/queryManagement'; import { ISaveRequest, SaveFormat } from 'sql/workbench/parts/grid/common/interfaces'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IWindowsService, IWindowService, FileFilter } from 'vs/platform/windows/common/windows'; import { Registry } from 'vs/platform/registry/common/platform'; import { URI } from 'vs/base/common/uri'; -import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService'; -import { Schemas } from 'vs/base/common/network'; import * as path from 'vs/base/common/path'; import * as nls from 'vs/nls'; -import * as pretty from 'pretty-data'; import Severity from 'vs/base/common/severity'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -38,13 +34,11 @@ let prevSavePath: string; */ export class ResultSerializer { public static tempFileCount: number = 1; - private static MAX_FILENAMES = 100; private _uri: string; private _filePath: string; constructor( - @IInstantiationService private _instantiationService: IInstantiationService, @IOutputService private _outputService: IOutputService, @IQueryManagementService private _queryManagementService: IQueryManagementService, @IConfigurationService private _workspaceConfigurationService: IConfigurationService, @@ -52,7 +46,6 @@ export class ResultSerializer { @IWorkspaceContextService private _contextService: IWorkspaceContextService, @IWindowsService private _windowsService: IWindowsService, @IWindowService private _windowService: IWindowService, - @IUntitledEditorService private _untitledEditorService: IUntitledEditorService, @INotificationService private _notificationService: INotificationService ) { } @@ -72,59 +65,6 @@ export class ResultSerializer { }); } - /** - * Open a xml/json link - Opens the content in a new editor pane - */ - public openLink(content: string, columnName: string, linkType: string): void { - let fileMode: string = undefined; - let fileUri = this.getUntitledFileUri(columnName); - - if (linkType === SaveFormat.XML) { - fileMode = SaveFormat.XML; - try { - content = pretty.pd.xml(content); - } catch (e) { - // If Xml fails to parse, fall back on original Xml content - } - } else if (linkType === SaveFormat.JSON) { - let jsonContent: string = undefined; - fileMode = SaveFormat.JSON; - try { - jsonContent = JSON.parse(content); - } catch (e) { - // If Json fails to parse, fall back on original Json content - } - if (jsonContent) { - // If Json content was valid and parsed, pretty print content to a string - content = JSON.stringify(jsonContent, undefined, 4); - } - } - - this.openUntitledFile(fileMode, content, fileUri); - } - - private getUntitledFileUri(columnName: string): URI { - let fileName = columnName; - - let uri: URI = URI.from({ scheme: Schemas.untitled, path: fileName }); - - // If the current filename is taken, try another up to a max number - if (this._untitledEditorService.exists(uri)) { - let i = 1; - while (i < ResultSerializer.MAX_FILENAMES - && this._untitledEditorService.exists(uri)) { - fileName = [columnName, i.toString()].join('-'); - uri = URI.from({ scheme: Schemas.untitled, path: fileName }); - i++; - } - if (this._untitledEditorService.exists(uri)) { - // If this fails, return undefined and let the system figure out the right name - uri = undefined; - } - } - return uri; - } - private ensureOutputChannelExists(): void { Registry.as(OutputExtensions.OutputChannels) .registerChannel({ @@ -387,23 +327,4 @@ export class ResultSerializer { }); } } - - /** - * Open the saved file in a new vscode editor pane - */ - private openUntitledFile(fileMode: string, contents: string, fileUri: URI = undefined): void { - const input = this._untitledEditorService.createOrGet(fileUri, fileMode, contents); - - this._editorService.openEditor(input, { pinned: true }) - .then( - (success) => { - }, - (error: any) => { - this._notificationService.notify({ - severity: Severity.Error, - message: error - }); - } - ); - } } diff --git a/src/sql/workbench/parts/grid/services/dataService.ts b/src/sql/workbench/parts/grid/services/dataService.ts index e18da8f8e3..a66383a66b 100644 --- a/src/sql/workbench/parts/grid/services/dataService.ts +++ b/src/sql/workbench/parts/grid/services/dataService.ts @@ -145,16 +145,6 @@ export class DataService { serializer.saveResults(this._uri, saveRequest); } - /** - * send request to open content in new editor - * @param content The content to be opened - * @param columnName The column name of the content - */ - openLink(content: string, columnName: string, linkType: string): void { - let serializer = this._instantiationService.createInstance(ResultSerializer); - serializer.openLink(content, columnName, linkType); - } - /** * Sends a copy request * @param selection The selection range to copy diff --git a/src/sql/workbench/parts/grid/views/gridParentComponent.ts b/src/sql/workbench/parts/grid/views/gridParentComponent.ts index 45175ea881..3444926b81 100644 --- a/src/sql/workbench/parts/grid/views/gridParentComponent.ts +++ b/src/sql/workbench/parts/grid/views/gridParentComponent.ts @@ -16,7 +16,6 @@ import { IGridInfo, IGridDataSet, SaveFormat } from 'sql/workbench/parts/grid/co import * as Utils from 'sql/platform/connection/common/utils'; import { DataService } from 'sql/workbench/parts/grid/services/dataService'; import * as actions from 'sql/workbench/parts/grid/views/gridActions'; -import * as Services from 'sql/base/browser/ui/table/formatters'; import * as GridContentEvents from 'sql/workbench/parts/grid/common/gridContentEvents'; import { ResultsVisibleContext, ResultsGridFocussedContext, ResultsMessagesFocussedContext, QueryEditorVisibleContext } from 'sql/workbench/parts/query/common/queryContext'; import { IQueryEditorService } from 'sql/workbench/services/queryEditor/common/queryEditorService'; @@ -487,65 +486,6 @@ export abstract class GridParentComponent { sel.addRange(range); } - /** - * Add handler for clicking on xml link - */ - xmlLinkHandler = (cellRef: string, row: number, dataContext: JSON, colDef: any) => { - const self = this; - - let value = self.getCellValueString(dataContext, colDef); - if (value.startsWith(' { - const self = this; - self.handleLink(cellRef, row, dataContext, colDef, 'json'); - } - - private handleQueryPlanLink(cellRef: string, value: string): void { - const self = this; - jQuery(cellRef).children('.xmlLink').click(function (): void { - self.queryEditorService.newQueryPlanEditor(value); - }); - } - - private handleLink(cellRef: string, row: number, dataContext: JSON, colDef: any, linkType: string): void { - const self = this; - let value = self.getCellValueString(dataContext, colDef); - jQuery(cellRef).children('.xmlLink').click(function (): void { - self.dataService.openLink(value, colDef.name, linkType); - }); - } - - private getCellValueString(dataContext: JSON, colDef: any): string { - let returnVal = ''; - let value = dataContext[colDef.field]; - if (Services.DBCellValue.isDBCellValue(value)) { - returnVal = value.displayValue; - } else if (typeof value === 'string') { - returnVal = value; - } - return returnVal; - } - - /** - * Return asyncPostRender handler based on type - */ - public linkHandler(type: string): Function { - if (type === 'xml') { - return this.xmlLinkHandler; - } else { // default to JSON handler - return this.jsonLinkHandler; - } - } - keyEvent(e: KeyboardEvent): void { if (this.tryHandleKeyEvent(new StandardKeyboardEvent(e))) { e.preventDefault(); diff --git a/src/sql/workbench/parts/query/electron-browser/gridPanel.ts b/src/sql/workbench/parts/query/electron-browser/gridPanel.ts index 1ce10b59b9..b55a95ab3f 100644 --- a/src/sql/workbench/parts/query/electron-browser/gridPanel.ts +++ b/src/sql/workbench/parts/query/electron-browser/gridPanel.ts @@ -3,8 +3,6 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as pretty from 'pretty-data'; - import { attachTableStyler } from 'sql/platform/theme/common/styler'; import QueryRunner from 'sql/platform/query/common/queryRunner'; import { VirtualizedCollection, AsyncDataProvider } from 'sql/base/browser/ui/table/asyncDataView'; @@ -41,6 +39,8 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IAction } from 'vs/base/common/actions'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { ILogService } from 'vs/platform/log/common/log'; +import { formatDocumentWithSelectedProvider, FormattingMode } from 'vs/editor/contrib/format/format'; +import { CancellationToken } from 'vs/base/common/cancellation'; const ROW_HEIGHT = 29; const HEADER_HEIGHT = 26; @@ -605,30 +605,14 @@ class GridTable extends Disposable implements IView { let column = this.resultSet.columnInfo[event.cell.cell - 1]; // handle if a showplan link was clicked if (column && (column.isXml || column.isJson)) { - this.runner.getQueryRows(event.cell.row, 1, this.resultSet.batchId, this.resultSet.id).then(d => { + this.runner.getQueryRows(event.cell.row, 1, this.resultSet.batchId, this.resultSet.id).then(async d => { let value = d.resultSubset.rows[0][event.cell.cell - 1]; let content = value.displayValue; - if (column.isXml) { - try { - content = pretty.pd.xml(content); - } catch (e) { - // If Xml fails to parse, fall back on original Xml content - } - } else { - let jsonContent: string = undefined; - try { - jsonContent = JSON.parse(content); - } catch (e) { - // If Json fails to parse, fall back on original Json content - } - if (jsonContent) { - // If Json content was valid and parsed, pretty print content to a string - content = JSON.stringify(jsonContent, undefined, 4); - } - } - let input = this.untitledEditorService.createOrGet(undefined, column.isXml ? 'xml' : 'json', content); - this.editorService.openEditor(input); + const input = this.untitledEditorService.createOrGet(undefined, column.isXml ? 'xml' : 'json', content); + const model = await input.resolve(); + await this.instantiationService.invokeFunction(formatDocumentWithSelectedProvider, model.textEditorModel, FormattingMode.Explicit, CancellationToken.None); + return this.editorService.openEditor(input); }); } } diff --git a/yarn.lock b/yarn.lock index e5e2e9b0f6..9b47d890a9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7091,11 +7091,6 @@ pretty-bytes@^1.0.2: get-stdin "^4.0.1" meow "^3.1.0" -pretty-data@^0.40.0: - version "0.40.0" - resolved "https://registry.yarnpkg.com/pretty-data/-/pretty-data-0.40.0.tgz#572aa8ea23467467ab94b6b5266a6fd9c8fddd72" - integrity sha1-Vyqo6iNGdGerlLa1Jmpv2cj93XI= - pretty-hrtime@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"