From 4640c6c44c41c83ea4311c186fae0988f5450da9 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Thu, 31 May 2018 18:19:34 -0400 Subject: [PATCH 01/10] Properly Ignore VSIX Files --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 8c8220a..a337458 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ out node_modules .vscode-test/ -.vsix +/*.vsix From 5a90a0c121e0bb5a9a5c9deaf3e15c916985697f Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Thu, 31 May 2018 18:41:52 -0400 Subject: [PATCH 02/10] Add Failing Test Issue: #185 --- src/test/extension.test.ts | 4 ++++ src/test/test-data/issue-185.formatted.xml | 5 +++++ src/test/test-data/issue-185.unformatted.xml | 1 + 3 files changed, 10 insertions(+) create mode 100644 src/test/test-data/issue-185.formatted.xml create mode 100644 src/test/test-data/issue-185.unformatted.xml diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index 50adb2b..e230267 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -68,6 +68,10 @@ describe("V2XmlFormatter", () => { options.enforcePrettySelfClosingTagOnFormat = false; }); + it("should properly format closing tag after self-closing tag", () => { + testFormatter(xmlFormatter, options, "issue-185"); + }); + }); }); diff --git a/src/test/test-data/issue-185.formatted.xml b/src/test/test-data/issue-185.formatted.xml new file mode 100644 index 0000000..c91115a --- /dev/null +++ b/src/test/test-data/issue-185.formatted.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/test/test-data/issue-185.unformatted.xml b/src/test/test-data/issue-185.unformatted.xml new file mode 100644 index 0000000..92db740 --- /dev/null +++ b/src/test/test-data/issue-185.unformatted.xml @@ -0,0 +1 @@ + \ No newline at end of file From 0b892f6f0345658f6a619621b42fcc9f035ba89a Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Thu, 31 May 2018 19:05:52 -0400 Subject: [PATCH 03/10] Indent Closing Tag After Self-Closing Tag Issue: #185 --- src/formatting/formatters/v2-xml-formatter.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/formatting/formatters/v2-xml-formatter.ts b/src/formatting/formatters/v2-xml-formatter.ts index c67b0c9..bed5f8a 100644 --- a/src/formatting/formatters/v2-xml-formatter.ts +++ b/src/formatting/formatters/v2-xml-formatter.ts @@ -169,7 +169,7 @@ export class V2XmlFormatter implements XmlFormatter { indentLevel--; // if the end tag immediately follows a line break, just add an indentation - // if the end tag immediately follows another end tag, add a line break and indent + // if the end tag immediately follows another end tag or a self-closing tag (issue #185), add a line break and indent // otherwise, this should be treated as a same-line end tag(ex. text) if (pc === "\n") { output += `${this._getIndent(options, indentLevel)}<`; @@ -179,6 +179,10 @@ export class V2XmlFormatter implements XmlFormatter { output += `${options.newLine}${this._getIndent(options, indentLevel)}<`; } + else if (pc === ">" && ppc === "/") { + output += `${this._getIndent(options, indentLevel)}<`; + } + else { output += "<"; } From 751e7a7e07402cfd1cd5b34bfa90c362d58756df Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Thu, 31 May 2018 21:53:19 -0400 Subject: [PATCH 04/10] Add Manifest Entries Issue: #184 --- package.json | 132 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 117 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index c4ec2b2..5362bf2 100644 --- a/package.json +++ b/package.json @@ -68,58 +68,160 @@ "title": "XML Tools Configuration", "type": "object", "properties": { + "xmlTools.core.useNewSettings": { + "type": "boolean", + "default": false, + "description": "Enables use of the new 'nested' settings instead of the current 'flattened' settings." + }, + "xmlTools.formatter.addSpaceBeforeSelfClose": { + "type": "boolean", + "default": true, + "description": "Ensures a space exists before the '/>' in self-closing tags.", + "scope": "resource" + }, + "xmlTools.formatter.implementation": { + "type": "string", + "default": "v2", + "description": "Defines the XML formatter implementation used for formatting and minification.", + "enum": [ + "classic", + "v2" + ], + "scope": "application" + }, + "xmlTools.formatter.splitAttributes": { + "type": "boolean", + "default": false, + "description": "Places each attribute (except the first) on a new line. Includes xmlns attributes.", + "scope": "resource" + }, + "xmlTools.formatter.splitXmlnsAttributes": { + "type": "boolean", + "default": false, + "description": "Places each xmlns attribute on a new line.", + "scope": "resource" + }, + "xmlTools.formatter.stripCommentsOnMinify": { + "type": "boolean", + "default": false, + "description": "Removes comments from XML during minification.", + "scope": "resource" + }, + "xmlTools.treeView.enabled": { + "type": "boolean", + "default": true, + "description": "Enables the XML Tree View feature.", + "scope": "application" + }, + "xmlTools.treeView.showMetadata": { + "type": "boolean", + "default": true, + "description": "Displays attributes such as 'children' and 'attributes' counts in the XML tree view.", + "scope": "application" + }, + "xmlTools.treeView.syncCursor": { + "type": "boolean", + "default": false, + "description": "Reveals an element or atribute in the tree view when clicked in the editor.", + "scope": "application" + }, + "xmlTools.xpath.ignoreDefaultNamespace": { + "type": "boolean", + "default": true, + "description": "Ignores default xmlns attributes.", + "scope": "application" + }, + "xmlTools.xpath.rememberLastQuery": { + "type": "boolean", + "default": true, + "description": "Remembers the last query you executed for the current file.", + "scope": "application" + }, + "xmlTools.xquery.executable": { + "type": "string", + "default": true, + "description": "The full path to the executable to use for executing scripts.", + "scope": "application" + }, + "xmlTools.xquery.executableArgs": { + "type": "array", + "default": [ + "-xquery", + "$(script)", + "-in", + "$(input)", + "-out", + "$(input).output.xml" + ], + "description": "Command-line arguments to pass to the executable.", + "scope": "application" + }, + "xmlTools.xquery.inputFileLimit": { + "type": "integer", + "default": 100, + "description": "The maximum number of input files to enumerate.", + "scope": "application" + }, + "xmlTools.xquery.inputFileSearchPattern": { + "type": "string", + "default": "**/*.xml", + "description": "The pattern used to search for input XML files.", + "scope": "application" + }, + + "xmlTools.enableXmlTreeView": { "type": "boolean", "default": true, - "description": "Enables the XML Document view in the explorer for XML documents.", + "description": "Deprecated. Use 'xmlTools.treeView.enabled' instead.", "scope": "window" }, "xmlTools.enableXmlTreeViewMetadata": { "type": "boolean", "default": true, - "description": "Enables attribute and child element counts in the XML Document view.", + "description": "Deprecated. Use 'xmlTools.treeView.showMetadata' instead.", "scope": "window" }, "xmlTools.enableXmlTreeViewCursorSync": { "type": "boolean", "default": false, - "description": "Enables auto-reveal of elements in the XML Document view when a start tag is clicked in the editor.", + "description": "Deprecated. Use 'xmlTools.treeView.syncCursor' instead.", "scope": "window" }, "xmlTools.enforcePrettySelfClosingTagOnFormat": { "type": "boolean", "default": false, - "description": "Enforces a space before the forward slash at the end of a self-closing XML tag.", + "description": "Deprecated. Use 'xmlTools.formatter.addSpaceBeforeSelfClose' instead.", "scope": "resource" }, "xmlTools.ignoreDefaultNamespace": { "type": "boolean", "default": true, - "description": "Ignore default xmlns attributes when evaluating XPath.", + "description": "Deprecated. Use 'xmlTools.xpath.ignoreDefaultNamespace' instead.", "scope": "window" }, "xmlTools.persistXPathQuery": { "type": "boolean", "default": true, - "description": "Remember the last XPath query used.", + "description": "Deprecated. Use 'xmlTools.xpath.rememberLastQuery' instead.", "scope": "window" }, "xmlTools.removeCommentsOnMinify": { "type": "boolean", "default": false, - "description": "Remove XML comments during minification.", + "description": "Deprecated. Use 'xmlTools.formatter.removeCommentsOnMinify' instead.", "scope": "resource" }, "xmlTools.splitAttributesOnFormat": { "type": "boolean", "default": false, - "description": "Put each attribute on a new line when formatting XML. Overrides `xmlTools.splitXmlsOnFormat` if set to `true`.", + "description": "Deprecated. Use 'xmlTools.formatter.splitAttributes' instead.", "scope": "resource" }, "xmlTools.splitXmlnsOnFormat": { "type": "boolean", "default": true, - "description": "Put each xmlns attribute on a new line when formatting XML.", + "description": "Deprecated. Use 'xmlTools.formatter.splitXmlnsAttributes' instead.", "scope": "resource" }, "xmlTools.xmlFormatterImplementation": { @@ -129,7 +231,7 @@ "v2" ], "default": "v2", - "description": "Supported XML Formatters: classic", + "description": "Deprecated. Use 'xmlTools.formatter.implementation' instead.", "scope": "window" }, "xmlTools.xqueryExecutionArguments": { @@ -140,27 +242,27 @@ "-in", "$(input)", "-out", - "$(input.output.xml" + "$(input).output.xml" ], - "description": "Arguments to be passed to the XQuery execution engine.", + "description": "Deprecated. Use 'xmlTools.xquery.executableArgs' instead.", "scope": "window" }, "xmlTools.xqueryExecutionEngine": { "type": "string", "default": "", - "description": "The full path to the executable to run when executing XQuery scripts.", + "description": "Deprecated. Use 'xmlTools.xquery.executable' instead.", "scope": "window" }, "xmlTools.xqueryExecutionInputLimit": { "type": "integer", "default": 100, - "description": "The maximum number of input files to enumerate when executing XQuery scripts.", + "description": "Deprecated. Use 'xmlTools.xquery.inputFileLimit' instead.", "scope": "window" }, "xmlTools.xqueryExecutionInputSearchPattern": { "type": "string", "default": "**/*.xml", - "description": "The pattern used to search for input XML files when executing XQuery scripts.", + "description": "Deprecated. Use 'xmlTools.xquery.inputFileSearchPattern' instead.", "scope": "window" } } From 939569a5d2398e0413ce03bb72bcf37def2dc123 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Thu, 31 May 2018 22:15:29 -0400 Subject: [PATCH 05/10] Update Existing Config Properties Issue: #184 --- package.json | 4 +- src/common/configuration.ts | 69 +++++++++++-------- src/extension.ts | 2 +- src/formatting/xml-formatter.ts | 2 +- src/formatting/xml-formatting-options.ts | 8 +-- src/tree-view/xml-tree-data-provider.ts | 6 +- src/xpath/commands/evaluateXPath.ts | 4 +- .../commands/executeXQuery.ts | 8 +-- 8 files changed, 56 insertions(+), 47 deletions(-) diff --git a/package.json b/package.json index 5362bf2..d286c4f 100644 --- a/package.json +++ b/package.json @@ -156,13 +156,13 @@ "description": "Command-line arguments to pass to the executable.", "scope": "application" }, - "xmlTools.xquery.inputFileLimit": { + "xmlTools.xquery.inputFilesLimit": { "type": "integer", "default": 100, "description": "The maximum number of input files to enumerate.", "scope": "application" }, - "xmlTools.xquery.inputFileSearchPattern": { + "xmlTools.xquery.inputFilesSearchPattern": { "type": "string", "default": "**/*.xml", "description": "The pattern used to search for input XML files.", diff --git a/src/common/configuration.ts b/src/common/configuration.ts index b1461d0..95cdf52 100644 --- a/src/common/configuration.ts +++ b/src/common/configuration.ts @@ -1,69 +1,78 @@ import { workspace, Uri } from "vscode"; const ExtensionTopLevelSection = "xmlTools"; +const UseNewSettingsSection = "core.useNewSettings"; export class Configuration { - static get enableXmlTreeView(): boolean { - return this._getForWindow("enableXmlTreeView"); + static get treeViewEnabled(): boolean { + return this._getForWindow("treeView.enabled", "enableXmlTreeView"); } - static get enableXmlTreeViewMetadata(): boolean { - return this._getForWindow("enableXmlTreeViewMetadata"); + static get treeViewShowMetadata(): boolean { + return this._getForWindow("treeView.showMetadata", "enableXmlTreeViewMetadata"); } - static get enableXmlTreeViewCursorSync(): boolean { - return this._getForWindow("enableXmlTreeViewCursorSync"); + static get treeViewSyncCursor(): boolean { + return this._getForWindow("treeView.syncCursor", "enableXmlTreeViewCursorSync"); } - static get ignoreDefaultNamespace(): boolean { - return this._getForWindow("ignoreDefaultNamespace"); + static get xpathIgnoreDefaultNamespace(): boolean { + return this._getForWindow("xpath.ignoreDefaultNamespace", "ignoreDefaultNamespace"); } - static get persistXPathQuery(): boolean { - return this._getForWindow("persistXPathQuery"); + static get xpathRememberLastQuery(): boolean { + return this._getForWindow("xpath.rememberLastQuery", "persistXPathQuery"); } - static get xmlFormatterImplementation(): string { - return this._getForWindow("xmlFormatterImplementation"); + static get formatterImplementation(): string { + return this._getForWindow("formatter.implementation", "xmlFormatterImplementation"); } - static get xqueryExecutionArguments(): string[] { - return this._getForWindow("xqueryExecutionArguments"); + static get xqueryExecutableArgs(): string[] { + return this._getForWindow("xquery.executableArgs", "xqueryExecutionArguments"); } - static get xqueryExecutionEngine(): string { - return this._getForWindow("xqueryExecutionEngine"); + static get xqueryExecutable(): string { + return this._getForWindow("xquery.executable", "xqueryExecutionEngine"); } - static get xqueryExecutionInputLimit(): number { - return this._getForWindow("xqueryExecutionInputLimit"); + static get xqueryInputFilesLimit(): number { + return this._getForWindow("xquery.inputFilesLimit", "xqueryExecutionInputLimit"); } - static get xqueryExecutionInputSearchPattern(): string { - return this._getForWindow("xqueryExecutionInputSearchPattern"); + static get xqueryInputFilesSearchPattern(): string { + return this._getForWindow("xquery.inputFilesSearchPattern", "xqueryExecutionInputSearchPattern"); } - static enforcePrettySelfClosingTagOnFormat(resource: Uri): boolean { - return this._getForResource("enforcePrettySelfClosingTagOnFormat", resource); + static formatterAddSpaceBeforeSelfClose(resource: Uri): boolean { + return this._getForResource("formatter.addSpaceBeforeSelfClose", resource, "enforcePrettySelfClosingTagOnFormat"); } - static removeCommentsOnMinify(resource: Uri): boolean { - return this._getForResource("removeCommentsOnMinify", resource); + static formatterRemoveCommentsOnMinify(resource: Uri): boolean { + return this._getForResource("formatter.removeCommentsOnMinify", resource, "removeCommentsOnMinify"); } - static splitAttributesOnFormat(resource: Uri): boolean { - return this._getForResource("splitAttributesOnFormat", resource); + static formatterSplitAttributes(resource: Uri): boolean { + return this._getForResource("formatter.splitAttributes", resource, "splitAttributesOnFormat"); } - static splitXmlnsOnFormat(resource: Uri): boolean { - return this._getForResource("splitXmlnsOnFormat", resource); + static formatterSplitXmlnsAttributes(resource: Uri): boolean { + return this._getForResource("formatter.splitXmlnsAttributes", resource, "splitXmlnsOnFormat"); } - private static _getForResource(section: string, resource: Uri): T { + private static _getForResource(section: string, resource: Uri, oldSection?: string): T { + if (oldSection && !workspace.getConfiguration(ExtensionTopLevelSection).get(UseNewSettingsSection)) { + section = oldSection; + } + return workspace.getConfiguration(ExtensionTopLevelSection, resource).get(section); } - private static _getForWindow(section: string): T { + private static _getForWindow(section: string, oldSection?: string): T { + if (oldSection && !workspace.getConfiguration(ExtensionTopLevelSection).get(UseNewSettingsSection)) { + section = oldSection; + } + return workspace.getConfiguration(ExtensionTopLevelSection).get(section); } } diff --git a/src/extension.ts b/src/extension.ts index ee975af..e7a30a3 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -47,7 +47,7 @@ export function activate(context: ExtensionContext) { treeDataProvider: treeViewDataProvider }); - if (Configuration.enableXmlTreeViewCursorSync) { + if (Configuration.treeViewSyncCursor) { window.onDidChangeTextEditorSelection(x => { if (x.kind === TextEditorSelectionChangeKind.Mouse && x.selections.length > 0) { treeView.reveal(treeViewDataProvider.getNodeAtPosition(x.selections[0].start)); diff --git a/src/formatting/xml-formatter.ts b/src/formatting/xml-formatter.ts index 01fb9ae..c32fc33 100644 --- a/src/formatting/xml-formatter.ts +++ b/src/formatting/xml-formatter.ts @@ -20,7 +20,7 @@ export class XmlFormatterFactory { return XmlFormatterFactory._xmlFormatter; } - const xmlFormatterImplementationSetting = Configuration.xmlFormatterImplementation; + const xmlFormatterImplementationSetting = Configuration.formatterImplementation; let xmlFormatterImplementation: XmlFormatter; switch (xmlFormatterImplementationSetting) { diff --git a/src/formatting/xml-formatting-options.ts b/src/formatting/xml-formatting-options.ts index 06782a1..f7fa9c1 100644 --- a/src/formatting/xml-formatting-options.ts +++ b/src/formatting/xml-formatting-options.ts @@ -16,11 +16,11 @@ export class XmlFormattingOptionsFactory { static getXmlFormattingOptions(formattingOptions: FormattingOptions, document: TextDocument): XmlFormattingOptions { return { editorOptions: formattingOptions, - enforcePrettySelfClosingTagOnFormat: Configuration.enforcePrettySelfClosingTagOnFormat(document.uri), + enforcePrettySelfClosingTagOnFormat: Configuration.formatterAddSpaceBeforeSelfClose(document.uri), newLine: (document.eol === EndOfLine.CRLF) ? "\r\n" : "\n", - removeCommentsOnMinify: Configuration.removeCommentsOnMinify(document.uri), - splitAttributesOnFormat: Configuration.splitAttributesOnFormat(document.uri), - splitXmlnsOnFormat: Configuration.splitXmlnsOnFormat(document.uri) + removeCommentsOnMinify: Configuration.formatterRemoveCommentsOnMinify(document.uri), + splitAttributesOnFormat: Configuration.formatterSplitAttributes(document.uri), + splitXmlnsOnFormat: Configuration.formatterSplitXmlnsAttributes(document.uri) }; } } diff --git a/src/tree-view/xml-tree-data-provider.ts b/src/tree-view/xml-tree-data-provider.ts index 106d0a1..5526c31 100644 --- a/src/tree-view/xml-tree-data-provider.ts +++ b/src/tree-view/xml-tree-data-provider.ts @@ -34,8 +34,8 @@ export class XmlTreeDataProvider implements TreeDataProvider { } getTreeItem(element: Node): TreeItem | Thenable { - const enableMetadata = Configuration.enableXmlTreeViewMetadata; - const enableSync = Configuration.enableXmlTreeViewCursorSync; + const enableMetadata = Configuration.treeViewShowMetadata; + const enableSync = Configuration.treeViewSyncCursor; const treeItem = new TreeItem(element.localName); @@ -138,7 +138,7 @@ export class XmlTreeDataProvider implements TreeDataProvider { return; } - const enableTreeView = Configuration.enableXmlTreeView; + const enableTreeView = Configuration.treeViewEnabled; NativeCommands.setContext(constants.contextKeys.xmlTreeViewEnabled, enableTreeView); diff --git a/src/xpath/commands/evaluateXPath.ts b/src/xpath/commands/evaluateXPath.ts index bc22d97..fcb5e5a 100644 --- a/src/xpath/commands/evaluateXPath.ts +++ b/src/xpath/commands/evaluateXPath.ts @@ -21,7 +21,7 @@ export async function evaluateXPath(editor: TextEditor, edit: TextEditorEdit): P const memento = ExtensionState.workspace || ExtensionState.global; // get the xpath persistence setting - const persistQueries = Configuration.persistXPathQuery; + const persistQueries = Configuration.xpathRememberLastQuery; // get the last query if there is one for this document // if not, try pulling the last query ran, regardless of document @@ -47,7 +47,7 @@ export async function evaluateXPath(editor: TextEditor, edit: TextEditorEdit): P return; } - const ignoreDefaultNamespace = Configuration.ignoreDefaultNamespace; + const ignoreDefaultNamespace = Configuration.xpathIgnoreDefaultNamespace; // run the query const xml = editor.document.getText(); diff --git a/src/xquery-execution/commands/executeXQuery.ts b/src/xquery-execution/commands/executeXQuery.ts index a74ed0e..7f295cb 100644 --- a/src/xquery-execution/commands/executeXQuery.ts +++ b/src/xquery-execution/commands/executeXQuery.ts @@ -15,8 +15,8 @@ export async function executeXQuery(editor: TextEditor, edit: TextEditorEdit): P return; } - const executable = Configuration.xqueryExecutionEngine; - let args = Configuration.xqueryExecutionArguments || []; + const executable = Configuration.xqueryExecutable; + let args = Configuration.xqueryExecutableArgs || []; if (!executable || executable === "") { const action = await window.showWarningMessage("An XQuery execution engine has not been defined.", "Define Now"); @@ -31,8 +31,8 @@ export async function executeXQuery(editor: TextEditor, edit: TextEditorEdit): P let inputFile: Uri; disposable = window.setStatusBarMessage("Searching for XML files in folder..."); - const searchPattern = Configuration.xqueryExecutionInputSearchPattern; - const inputLimit = Configuration.xqueryExecutionInputLimit; + const searchPattern = Configuration.xqueryInputFilesSearchPattern; + const inputLimit = Configuration.xqueryInputFilesLimit; const files = await workspace.findFiles(searchPattern, "", inputLimit); From de1fff2e80fd0ae3e026c53f65b10abc4b168d7d Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Mon, 11 Jun 2018 18:29:35 -0400 Subject: [PATCH 06/10] Revert Settings Changes I'll come back to this later after some better planning. Issue: #184 --- package.json | 132 ++---------------- src/common/configuration.ts | 69 ++++----- src/extension.ts | 2 +- src/formatting/xml-formatter.ts | 2 +- src/formatting/xml-formatting-options.ts | 8 +- src/tree-view/xml-tree-data-provider.ts | 6 +- src/xpath/commands/evaluateXPath.ts | 4 +- .../commands/executeXQuery.ts | 8 +- 8 files changed, 60 insertions(+), 171 deletions(-) diff --git a/package.json b/package.json index d286c4f..c4ec2b2 100644 --- a/package.json +++ b/package.json @@ -68,160 +68,58 @@ "title": "XML Tools Configuration", "type": "object", "properties": { - "xmlTools.core.useNewSettings": { - "type": "boolean", - "default": false, - "description": "Enables use of the new 'nested' settings instead of the current 'flattened' settings." - }, - "xmlTools.formatter.addSpaceBeforeSelfClose": { - "type": "boolean", - "default": true, - "description": "Ensures a space exists before the '/>' in self-closing tags.", - "scope": "resource" - }, - "xmlTools.formatter.implementation": { - "type": "string", - "default": "v2", - "description": "Defines the XML formatter implementation used for formatting and minification.", - "enum": [ - "classic", - "v2" - ], - "scope": "application" - }, - "xmlTools.formatter.splitAttributes": { - "type": "boolean", - "default": false, - "description": "Places each attribute (except the first) on a new line. Includes xmlns attributes.", - "scope": "resource" - }, - "xmlTools.formatter.splitXmlnsAttributes": { - "type": "boolean", - "default": false, - "description": "Places each xmlns attribute on a new line.", - "scope": "resource" - }, - "xmlTools.formatter.stripCommentsOnMinify": { - "type": "boolean", - "default": false, - "description": "Removes comments from XML during minification.", - "scope": "resource" - }, - "xmlTools.treeView.enabled": { - "type": "boolean", - "default": true, - "description": "Enables the XML Tree View feature.", - "scope": "application" - }, - "xmlTools.treeView.showMetadata": { - "type": "boolean", - "default": true, - "description": "Displays attributes such as 'children' and 'attributes' counts in the XML tree view.", - "scope": "application" - }, - "xmlTools.treeView.syncCursor": { - "type": "boolean", - "default": false, - "description": "Reveals an element or atribute in the tree view when clicked in the editor.", - "scope": "application" - }, - "xmlTools.xpath.ignoreDefaultNamespace": { - "type": "boolean", - "default": true, - "description": "Ignores default xmlns attributes.", - "scope": "application" - }, - "xmlTools.xpath.rememberLastQuery": { - "type": "boolean", - "default": true, - "description": "Remembers the last query you executed for the current file.", - "scope": "application" - }, - "xmlTools.xquery.executable": { - "type": "string", - "default": true, - "description": "The full path to the executable to use for executing scripts.", - "scope": "application" - }, - "xmlTools.xquery.executableArgs": { - "type": "array", - "default": [ - "-xquery", - "$(script)", - "-in", - "$(input)", - "-out", - "$(input).output.xml" - ], - "description": "Command-line arguments to pass to the executable.", - "scope": "application" - }, - "xmlTools.xquery.inputFilesLimit": { - "type": "integer", - "default": 100, - "description": "The maximum number of input files to enumerate.", - "scope": "application" - }, - "xmlTools.xquery.inputFilesSearchPattern": { - "type": "string", - "default": "**/*.xml", - "description": "The pattern used to search for input XML files.", - "scope": "application" - }, - - "xmlTools.enableXmlTreeView": { "type": "boolean", "default": true, - "description": "Deprecated. Use 'xmlTools.treeView.enabled' instead.", + "description": "Enables the XML Document view in the explorer for XML documents.", "scope": "window" }, "xmlTools.enableXmlTreeViewMetadata": { "type": "boolean", "default": true, - "description": "Deprecated. Use 'xmlTools.treeView.showMetadata' instead.", + "description": "Enables attribute and child element counts in the XML Document view.", "scope": "window" }, "xmlTools.enableXmlTreeViewCursorSync": { "type": "boolean", "default": false, - "description": "Deprecated. Use 'xmlTools.treeView.syncCursor' instead.", + "description": "Enables auto-reveal of elements in the XML Document view when a start tag is clicked in the editor.", "scope": "window" }, "xmlTools.enforcePrettySelfClosingTagOnFormat": { "type": "boolean", "default": false, - "description": "Deprecated. Use 'xmlTools.formatter.addSpaceBeforeSelfClose' instead.", + "description": "Enforces a space before the forward slash at the end of a self-closing XML tag.", "scope": "resource" }, "xmlTools.ignoreDefaultNamespace": { "type": "boolean", "default": true, - "description": "Deprecated. Use 'xmlTools.xpath.ignoreDefaultNamespace' instead.", + "description": "Ignore default xmlns attributes when evaluating XPath.", "scope": "window" }, "xmlTools.persistXPathQuery": { "type": "boolean", "default": true, - "description": "Deprecated. Use 'xmlTools.xpath.rememberLastQuery' instead.", + "description": "Remember the last XPath query used.", "scope": "window" }, "xmlTools.removeCommentsOnMinify": { "type": "boolean", "default": false, - "description": "Deprecated. Use 'xmlTools.formatter.removeCommentsOnMinify' instead.", + "description": "Remove XML comments during minification.", "scope": "resource" }, "xmlTools.splitAttributesOnFormat": { "type": "boolean", "default": false, - "description": "Deprecated. Use 'xmlTools.formatter.splitAttributes' instead.", + "description": "Put each attribute on a new line when formatting XML. Overrides `xmlTools.splitXmlsOnFormat` if set to `true`.", "scope": "resource" }, "xmlTools.splitXmlnsOnFormat": { "type": "boolean", "default": true, - "description": "Deprecated. Use 'xmlTools.formatter.splitXmlnsAttributes' instead.", + "description": "Put each xmlns attribute on a new line when formatting XML.", "scope": "resource" }, "xmlTools.xmlFormatterImplementation": { @@ -231,7 +129,7 @@ "v2" ], "default": "v2", - "description": "Deprecated. Use 'xmlTools.formatter.implementation' instead.", + "description": "Supported XML Formatters: classic", "scope": "window" }, "xmlTools.xqueryExecutionArguments": { @@ -242,27 +140,27 @@ "-in", "$(input)", "-out", - "$(input).output.xml" + "$(input.output.xml" ], - "description": "Deprecated. Use 'xmlTools.xquery.executableArgs' instead.", + "description": "Arguments to be passed to the XQuery execution engine.", "scope": "window" }, "xmlTools.xqueryExecutionEngine": { "type": "string", "default": "", - "description": "Deprecated. Use 'xmlTools.xquery.executable' instead.", + "description": "The full path to the executable to run when executing XQuery scripts.", "scope": "window" }, "xmlTools.xqueryExecutionInputLimit": { "type": "integer", "default": 100, - "description": "Deprecated. Use 'xmlTools.xquery.inputFileLimit' instead.", + "description": "The maximum number of input files to enumerate when executing XQuery scripts.", "scope": "window" }, "xmlTools.xqueryExecutionInputSearchPattern": { "type": "string", "default": "**/*.xml", - "description": "Deprecated. Use 'xmlTools.xquery.inputFileSearchPattern' instead.", + "description": "The pattern used to search for input XML files when executing XQuery scripts.", "scope": "window" } } diff --git a/src/common/configuration.ts b/src/common/configuration.ts index 95cdf52..b1461d0 100644 --- a/src/common/configuration.ts +++ b/src/common/configuration.ts @@ -1,78 +1,69 @@ import { workspace, Uri } from "vscode"; const ExtensionTopLevelSection = "xmlTools"; -const UseNewSettingsSection = "core.useNewSettings"; export class Configuration { - static get treeViewEnabled(): boolean { - return this._getForWindow("treeView.enabled", "enableXmlTreeView"); + static get enableXmlTreeView(): boolean { + return this._getForWindow("enableXmlTreeView"); } - static get treeViewShowMetadata(): boolean { - return this._getForWindow("treeView.showMetadata", "enableXmlTreeViewMetadata"); + static get enableXmlTreeViewMetadata(): boolean { + return this._getForWindow("enableXmlTreeViewMetadata"); } - static get treeViewSyncCursor(): boolean { - return this._getForWindow("treeView.syncCursor", "enableXmlTreeViewCursorSync"); + static get enableXmlTreeViewCursorSync(): boolean { + return this._getForWindow("enableXmlTreeViewCursorSync"); } - static get xpathIgnoreDefaultNamespace(): boolean { - return this._getForWindow("xpath.ignoreDefaultNamespace", "ignoreDefaultNamespace"); + static get ignoreDefaultNamespace(): boolean { + return this._getForWindow("ignoreDefaultNamespace"); } - static get xpathRememberLastQuery(): boolean { - return this._getForWindow("xpath.rememberLastQuery", "persistXPathQuery"); + static get persistXPathQuery(): boolean { + return this._getForWindow("persistXPathQuery"); } - static get formatterImplementation(): string { - return this._getForWindow("formatter.implementation", "xmlFormatterImplementation"); + static get xmlFormatterImplementation(): string { + return this._getForWindow("xmlFormatterImplementation"); } - static get xqueryExecutableArgs(): string[] { - return this._getForWindow("xquery.executableArgs", "xqueryExecutionArguments"); + static get xqueryExecutionArguments(): string[] { + return this._getForWindow("xqueryExecutionArguments"); } - static get xqueryExecutable(): string { - return this._getForWindow("xquery.executable", "xqueryExecutionEngine"); + static get xqueryExecutionEngine(): string { + return this._getForWindow("xqueryExecutionEngine"); } - static get xqueryInputFilesLimit(): number { - return this._getForWindow("xquery.inputFilesLimit", "xqueryExecutionInputLimit"); + static get xqueryExecutionInputLimit(): number { + return this._getForWindow("xqueryExecutionInputLimit"); } - static get xqueryInputFilesSearchPattern(): string { - return this._getForWindow("xquery.inputFilesSearchPattern", "xqueryExecutionInputSearchPattern"); + static get xqueryExecutionInputSearchPattern(): string { + return this._getForWindow("xqueryExecutionInputSearchPattern"); } - static formatterAddSpaceBeforeSelfClose(resource: Uri): boolean { - return this._getForResource("formatter.addSpaceBeforeSelfClose", resource, "enforcePrettySelfClosingTagOnFormat"); + static enforcePrettySelfClosingTagOnFormat(resource: Uri): boolean { + return this._getForResource("enforcePrettySelfClosingTagOnFormat", resource); } - static formatterRemoveCommentsOnMinify(resource: Uri): boolean { - return this._getForResource("formatter.removeCommentsOnMinify", resource, "removeCommentsOnMinify"); + static removeCommentsOnMinify(resource: Uri): boolean { + return this._getForResource("removeCommentsOnMinify", resource); } - static formatterSplitAttributes(resource: Uri): boolean { - return this._getForResource("formatter.splitAttributes", resource, "splitAttributesOnFormat"); + static splitAttributesOnFormat(resource: Uri): boolean { + return this._getForResource("splitAttributesOnFormat", resource); } - static formatterSplitXmlnsAttributes(resource: Uri): boolean { - return this._getForResource("formatter.splitXmlnsAttributes", resource, "splitXmlnsOnFormat"); + static splitXmlnsOnFormat(resource: Uri): boolean { + return this._getForResource("splitXmlnsOnFormat", resource); } - private static _getForResource(section: string, resource: Uri, oldSection?: string): T { - if (oldSection && !workspace.getConfiguration(ExtensionTopLevelSection).get(UseNewSettingsSection)) { - section = oldSection; - } - + private static _getForResource(section: string, resource: Uri): T { return workspace.getConfiguration(ExtensionTopLevelSection, resource).get(section); } - private static _getForWindow(section: string, oldSection?: string): T { - if (oldSection && !workspace.getConfiguration(ExtensionTopLevelSection).get(UseNewSettingsSection)) { - section = oldSection; - } - + private static _getForWindow(section: string): T { return workspace.getConfiguration(ExtensionTopLevelSection).get(section); } } diff --git a/src/extension.ts b/src/extension.ts index e7a30a3..ee975af 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -47,7 +47,7 @@ export function activate(context: ExtensionContext) { treeDataProvider: treeViewDataProvider }); - if (Configuration.treeViewSyncCursor) { + if (Configuration.enableXmlTreeViewCursorSync) { window.onDidChangeTextEditorSelection(x => { if (x.kind === TextEditorSelectionChangeKind.Mouse && x.selections.length > 0) { treeView.reveal(treeViewDataProvider.getNodeAtPosition(x.selections[0].start)); diff --git a/src/formatting/xml-formatter.ts b/src/formatting/xml-formatter.ts index c32fc33..01fb9ae 100644 --- a/src/formatting/xml-formatter.ts +++ b/src/formatting/xml-formatter.ts @@ -20,7 +20,7 @@ export class XmlFormatterFactory { return XmlFormatterFactory._xmlFormatter; } - const xmlFormatterImplementationSetting = Configuration.formatterImplementation; + const xmlFormatterImplementationSetting = Configuration.xmlFormatterImplementation; let xmlFormatterImplementation: XmlFormatter; switch (xmlFormatterImplementationSetting) { diff --git a/src/formatting/xml-formatting-options.ts b/src/formatting/xml-formatting-options.ts index f7fa9c1..06782a1 100644 --- a/src/formatting/xml-formatting-options.ts +++ b/src/formatting/xml-formatting-options.ts @@ -16,11 +16,11 @@ export class XmlFormattingOptionsFactory { static getXmlFormattingOptions(formattingOptions: FormattingOptions, document: TextDocument): XmlFormattingOptions { return { editorOptions: formattingOptions, - enforcePrettySelfClosingTagOnFormat: Configuration.formatterAddSpaceBeforeSelfClose(document.uri), + enforcePrettySelfClosingTagOnFormat: Configuration.enforcePrettySelfClosingTagOnFormat(document.uri), newLine: (document.eol === EndOfLine.CRLF) ? "\r\n" : "\n", - removeCommentsOnMinify: Configuration.formatterRemoveCommentsOnMinify(document.uri), - splitAttributesOnFormat: Configuration.formatterSplitAttributes(document.uri), - splitXmlnsOnFormat: Configuration.formatterSplitXmlnsAttributes(document.uri) + removeCommentsOnMinify: Configuration.removeCommentsOnMinify(document.uri), + splitAttributesOnFormat: Configuration.splitAttributesOnFormat(document.uri), + splitXmlnsOnFormat: Configuration.splitXmlnsOnFormat(document.uri) }; } } diff --git a/src/tree-view/xml-tree-data-provider.ts b/src/tree-view/xml-tree-data-provider.ts index 5526c31..106d0a1 100644 --- a/src/tree-view/xml-tree-data-provider.ts +++ b/src/tree-view/xml-tree-data-provider.ts @@ -34,8 +34,8 @@ export class XmlTreeDataProvider implements TreeDataProvider { } getTreeItem(element: Node): TreeItem | Thenable { - const enableMetadata = Configuration.treeViewShowMetadata; - const enableSync = Configuration.treeViewSyncCursor; + const enableMetadata = Configuration.enableXmlTreeViewMetadata; + const enableSync = Configuration.enableXmlTreeViewCursorSync; const treeItem = new TreeItem(element.localName); @@ -138,7 +138,7 @@ export class XmlTreeDataProvider implements TreeDataProvider { return; } - const enableTreeView = Configuration.treeViewEnabled; + const enableTreeView = Configuration.enableXmlTreeView; NativeCommands.setContext(constants.contextKeys.xmlTreeViewEnabled, enableTreeView); diff --git a/src/xpath/commands/evaluateXPath.ts b/src/xpath/commands/evaluateXPath.ts index fcb5e5a..bc22d97 100644 --- a/src/xpath/commands/evaluateXPath.ts +++ b/src/xpath/commands/evaluateXPath.ts @@ -21,7 +21,7 @@ export async function evaluateXPath(editor: TextEditor, edit: TextEditorEdit): P const memento = ExtensionState.workspace || ExtensionState.global; // get the xpath persistence setting - const persistQueries = Configuration.xpathRememberLastQuery; + const persistQueries = Configuration.persistXPathQuery; // get the last query if there is one for this document // if not, try pulling the last query ran, regardless of document @@ -47,7 +47,7 @@ export async function evaluateXPath(editor: TextEditor, edit: TextEditorEdit): P return; } - const ignoreDefaultNamespace = Configuration.xpathIgnoreDefaultNamespace; + const ignoreDefaultNamespace = Configuration.ignoreDefaultNamespace; // run the query const xml = editor.document.getText(); diff --git a/src/xquery-execution/commands/executeXQuery.ts b/src/xquery-execution/commands/executeXQuery.ts index 7f295cb..a74ed0e 100644 --- a/src/xquery-execution/commands/executeXQuery.ts +++ b/src/xquery-execution/commands/executeXQuery.ts @@ -15,8 +15,8 @@ export async function executeXQuery(editor: TextEditor, edit: TextEditorEdit): P return; } - const executable = Configuration.xqueryExecutable; - let args = Configuration.xqueryExecutableArgs || []; + const executable = Configuration.xqueryExecutionEngine; + let args = Configuration.xqueryExecutionArguments || []; if (!executable || executable === "") { const action = await window.showWarningMessage("An XQuery execution engine has not been defined.", "Define Now"); @@ -31,8 +31,8 @@ export async function executeXQuery(editor: TextEditor, edit: TextEditorEdit): P let inputFile: Uri; disposable = window.setStatusBarMessage("Searching for XML files in folder..."); - const searchPattern = Configuration.xqueryInputFilesSearchPattern; - const inputLimit = Configuration.xqueryInputFilesLimit; + const searchPattern = Configuration.xqueryExecutionInputSearchPattern; + const inputLimit = Configuration.xqueryExecutionInputLimit; const files = await workspace.findFiles(searchPattern, "", inputLimit); From b50cdaea8efd6a0f6c9b959e2ee18200aeb69023 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Mon, 11 Jun 2018 18:38:42 -0400 Subject: [PATCH 07/10] Add Failing Test Issue: #187 --- src/test/extension.test.ts | 4 ++++ src/test/test-data/issue-187.formatted.xml | 17 +++++++++++++++++ src/test/test-data/issue-187.unformatted.xml | 17 +++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 src/test/test-data/issue-187.formatted.xml create mode 100644 src/test/test-data/issue-187.unformatted.xml diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index e230267..7eb816a 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -72,6 +72,10 @@ describe("V2XmlFormatter", () => { testFormatter(xmlFormatter, options, "issue-185"); }); + it("should support single quotes within double-quoptes attributes and vice-versa", () => { + testFormatter(xmlFormatter, options, "issue-187"); + }); + }); }); diff --git a/src/test/test-data/issue-187.formatted.xml b/src/test/test-data/issue-187.formatted.xml new file mode 100644 index 0000000..2ad9048 --- /dev/null +++ b/src/test/test-data/issue-187.formatted.xml @@ -0,0 +1,17 @@ + + + Debug + latest + + + false + None + true + + + + + + + + \ No newline at end of file diff --git a/src/test/test-data/issue-187.unformatted.xml b/src/test/test-data/issue-187.unformatted.xml new file mode 100644 index 0000000..2ad9048 --- /dev/null +++ b/src/test/test-data/issue-187.unformatted.xml @@ -0,0 +1,17 @@ + + + Debug + latest + + + false + None + true + + + + + + + + \ No newline at end of file From 88de7743891b035fb42627d36939992bdd63969f Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Mon, 11 Jun 2018 18:40:54 -0400 Subject: [PATCH 08/10] Fix Attribute Quotes Regression Issue: #187 --- src/formatting/formatters/v2-xml-formatter.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/formatting/formatters/v2-xml-formatter.ts b/src/formatting/formatters/v2-xml-formatter.ts index bed5f8a..0d8af2a 100644 --- a/src/formatting/formatters/v2-xml-formatter.ts +++ b/src/formatting/formatters/v2-xml-formatter.ts @@ -32,6 +32,7 @@ export class V2XmlFormatter implements XmlFormatter { let indentLevel = 0; let location = Location.Text; let lastNonTextLocation = Location.Text; // hah + let attributeQuote = ""; // NOTE: all "exiting" checks should appear after their associated "entering" checks for (let i = 0; i < xml.length; i++) { @@ -126,13 +127,17 @@ export class V2XmlFormatter implements XmlFormatter { output += cc; lastNonTextLocation = location; location = Location.AttributeValue; + + attributeQuote = cc; } // exiting StartTag.Attribute.AttributeValue, entering StartTag - else if (location === Location.AttributeValue && (cc === "\"" || cc === "'")) { + else if (location === Location.AttributeValue && cc === attributeQuote) { output += cc; lastNonTextLocation = location; location = Location.StartTag; + + attributeQuote = undefined; } // approaching the end of a self-closing tag where there was no whitespace (issue #149) From 39167c3252310a15363572d9159b8f17f5a19bb8 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Mon, 11 Jun 2018 18:58:54 -0400 Subject: [PATCH 09/10] Add Attribute Values Test Case Issue: #189 --- src/test/extension.test.ts | 4 ++++ src/test/test-data/issue-189.formatted.xml | 5 +++++ src/test/test-data/issue-189.unformatted.xml | 5 +++++ 3 files changed, 14 insertions(+) create mode 100644 src/test/test-data/issue-189.formatted.xml create mode 100644 src/test/test-data/issue-189.unformatted.xml diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index 7eb816a..45666e7 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -76,6 +76,10 @@ describe("V2XmlFormatter", () => { testFormatter(xmlFormatter, options, "issue-187"); }); + it("should not ruin attributes with unusual characters", () => { + testFormatter(xmlFormatter, options, "issue-189"); + }); + }); }); diff --git a/src/test/test-data/issue-189.formatted.xml b/src/test/test-data/issue-189.formatted.xml new file mode 100644 index 0000000..b3a3d19 --- /dev/null +++ b/src/test/test-data/issue-189.formatted.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/src/test/test-data/issue-189.unformatted.xml b/src/test/test-data/issue-189.unformatted.xml new file mode 100644 index 0000000..952ff72 --- /dev/null +++ b/src/test/test-data/issue-189.unformatted.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file From a29b2fc1de9e2d30805595d7a1ef69fa5958bf46 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Mon, 11 Jun 2018 19:31:49 -0400 Subject: [PATCH 10/10] v2.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c4ec2b2..009eb8c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "xml", "displayName": "XML Tools", "description": "XML Formatting, XQuery, and XPath Tools for Visual Studio Code", - "version": "2.2.0", + "version": "2.3.0", "preview": false, "publisher": "DotJoshJohnson", "author": {