XML Formatter (#6182)

* add xml formatter extenstion

* remove unused imports
This commit is contained in:
Anthony Dresser
2019-06-27 12:20:19 -07:00
committed by GitHub
parent 20bbaa3fe6
commit 7b6181de2a
16 changed files with 109 additions and 196 deletions

View File

@@ -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<IOutputChannelRegistry>(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
});
}
);
}
}

View File

@@ -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

View File

@@ -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('<ShowPlanXML') && colDef.name !== 'XML Showplan') {
self.handleQueryPlanLink(cellRef, value);
} else {
self.handleLink(cellRef, row, dataContext, colDef, 'xml');
}
}
/**
* Add handler for clicking on json link
*/
jsonLinkHandler = (cellRef: string, row: number, dataContext: JSON, colDef: any) => {
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();

View File

@@ -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<T> 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);
});
}
}