From a4366a5061bf98ced7ea7fc887b400c1687b161e Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Thu, 3 May 2018 22:36:54 -0400 Subject: [PATCH] Add Configuration Service --- package.json | 14 ++-- src/common/configuration.ts | 65 +++++++++++++++++++ src/common/index.ts | 1 + src/constants.ts | 15 ----- src/extension.ts | 8 +-- src/formatting/commands/formatAsXml.ts | 2 +- src/formatting/commands/minifyXml.ts | 2 +- src/formatting/xml-formatter.ts | 3 +- .../xml-formatting-edit-provider.ts | 8 +-- src/formatting/xml-formatting-options.ts | 16 ++--- src/tree-view/xml-tree-data-provider.ts | 12 ++-- src/xpath/commands/evaluateXPath.ts | 10 ++- .../commands/executeXQuery.ts | 11 ++-- 13 files changed, 103 insertions(+), 64 deletions(-) create mode 100644 src/common/configuration.ts diff --git a/package.json b/package.json index 634594d..26187d8 100644 --- a/package.json +++ b/package.json @@ -85,13 +85,13 @@ "type": "boolean", "default": true, "description": "Ignore default xmlns attributes when evaluating XPath.", - "scope": "resource" + "scope": "window" }, "xmlTools.persistXPathQuery": { "type": "boolean", "default": true, "description": "Remember the last XPath query used.", - "scope": "resource" + "scope": "window" }, "xmlTools.removeCommentsOnMinify": { "type": "boolean", @@ -115,7 +115,7 @@ "type": "string", "default": "v2", "description": "Supported XML Formatters: classic", - "scope": "resource" + "scope": "window" }, "xmlTools.xqueryExecutionArguments": { "type": "array", @@ -128,25 +128,25 @@ "$(input.output.xml" ], "description": "Arguments to be passed to the XQuery execution engine.", - "scope": "resource" + "scope": "window" }, "xmlTools.xqueryExecutionEngine": { "type": "string", "default": "", "description": "The full path to the executable to run when executing XQuery scripts.", - "scope": "resource" + "scope": "window" }, "xmlTools.xqueryExecutionInputLimit": { "type": "integer", "default": 100, "description": "The maximum number of input files to enumerate when executing XQuery scripts.", - "scope": "resource" + "scope": "window" }, "xmlTools.xqueryExecutionInputSearchPattern": { "type": "string", "default": "**/*.xml", "description": "The pattern used to search for input XML files when executing XQuery scripts.", - "scope": "resource" + "scope": "window" } } }, diff --git a/src/common/configuration.ts b/src/common/configuration.ts new file mode 100644 index 0000000..0a3ef1c --- /dev/null +++ b/src/common/configuration.ts @@ -0,0 +1,65 @@ +import { workspace, Uri } from "vscode"; + +const ExtensionTopLevelSection = "xmlTools"; + +export class Configuration { + static get enableXmlTreeView(): boolean { + return this._getForWindow("enableXmlTreeView"); + } + + static get enableXmlTreeViewMetadata(): boolean { + return this._getForWindow("enableXmlTreeViewMetadata"); + } + + static get enableXmlTreeViewCursorSync(): boolean { + return this._getForWindow("enableXmlTreeViewCursorSync"); + } + + static get ignoreDefaultNamespace(): boolean { + return this._getForWindow("ignoreDefaultNamespace"); + } + + static get persistXPathQuery(): boolean { + return this._getForWindow("persistXPathQuery"); + } + + static get xmlFormatterImplementation(): string { + return this._getForWindow("xmlFormatterImplementation"); + } + + static get xqueryExecutionArguments(): string[] { + return this._getForWindow("xqueryExecutionArguments"); + } + + static get xqueryExecutionEngine(): string { + return this._getForWindow("xqueryExecutionEngine"); + } + + static get xqueryExecutionInputLimit(): number { + return this._getForWindow("xqueryExecutionInputLimit"); + } + + static get xqueryExecutionInputSearchPattern(): string { + return this._getForWindow("xqueryExecutionInputSearchPattern"); + } + + static removeCommentsOnMinify(resource: Uri): boolean { + return this._getForResource("removeCommentsOnMinify", resource); + } + + static splitAttributesOnFormat(resource: Uri): boolean { + return this._getForResource("splitAttributesOnFormat", resource); + } + + static splitXmlnsOnFormat(resource: Uri): boolean { + return this._getForResource("splitXmlnsOnFormat", resource); + } + + private static _getForResource(section: string, resource: Uri): T { + return workspace.getConfiguration(ExtensionTopLevelSection, resource).get(section); + } + + private static _getForWindow(section: string): T { + return workspace.getConfiguration(ExtensionTopLevelSection).get(section); + } +} diff --git a/src/common/index.ts b/src/common/index.ts index b322d14..ead1cdb 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -1,2 +1,3 @@ +export * from "./configuration"; export * from "./create-document-selector"; export * from "./extension-state"; diff --git a/src/constants.ts b/src/constants.ts index 8f1237d..5732939 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -11,21 +11,6 @@ export namespace contextKeys { export const xmlTreeViewEnabled = "xmlTreeViewEnabled"; } -export namespace configKeys { - export const enableXmlTreeView = "enableXmlTreeView"; - export const enableXmlTreeViewMetadata = "enableXmlTreeViewMetadata"; - export const enableXmlTreeViewCursorSync = "enableXmlTreeViewCursorSync"; - export const ignoreDefaultNamespace = "ignoreDefaultNamespace"; - export const persistXPathQuery = "persistXPathQuery"; - export const removeCommentsOnMinify = "removeCommentsOnMinify"; - export const splitAttributesOnFormat = "splitAttributesOnFormat"; - export const splitXmlnsOnFormat = "splitXmlnsOnFormat"; - export const xqueryExecutionArguments = "xqueryExecutionArguments"; - export const xqueryExecutionEngine = "xqueryExecutionEngine"; - export const xqueryExecutionInputLimit = "xqueryExecutionInputLimit"; - export const xqueryExecutionInputSearchPattern = "xqueryExecutionInputSearchPattern"; -} - export namespace diagnosticCollections { export const xquery = "XQueryDiagnostics"; } diff --git a/src/extension.ts b/src/extension.ts index 2cad6cf..276d9df 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -3,7 +3,7 @@ import { TextEditor, TextEditorSelectionChangeEvent, TextEditorSelectionChangeKind } from "vscode"; -import { createDocumentSelector, ExtensionState } from "./common"; +import { createDocumentSelector, ExtensionState, Configuration } from "./common"; import { XQueryCompletionItemProvider } from "./completion"; import { XmlFormatterFactory, XmlFormattingEditProvider } from "./formatting"; import { formatAsXml, minifyXml } from "./formatting/commands"; @@ -17,8 +17,6 @@ import * as constants from "./constants"; export function activate(context: ExtensionContext) { ExtensionState.configure(context); - const config = workspace.getConfiguration(constants.extensionPrefix); - const xmlXsdDocSelector = [...createDocumentSelector(constants.languageIds.xml), ...createDocumentSelector(constants.languageIds.xsd)]; const xqueryDocSelector = createDocumentSelector(constants.languageIds.xquery); @@ -28,7 +26,7 @@ export function activate(context: ExtensionContext) { ); /* Formatting Features */ - const xmlFormattingEditProvider = new XmlFormattingEditProvider(config, XmlFormatterFactory.getXmlFormatter()); + const xmlFormattingEditProvider = new XmlFormattingEditProvider(XmlFormatterFactory.getXmlFormatter()); context.subscriptions.push( commands.registerTextEditorCommand(constants.commands.formatAsXml, formatAsXml), @@ -49,7 +47,7 @@ export function activate(context: ExtensionContext) { treeDataProvider: treeViewDataProvider }); - if (config.get(constants.configKeys.enableXmlTreeViewCursorSync)) { + 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/commands/formatAsXml.ts b/src/formatting/commands/formatAsXml.ts index a1b589e..c0d64a1 100644 --- a/src/formatting/commands/formatAsXml.ts +++ b/src/formatting/commands/formatAsXml.ts @@ -8,7 +8,7 @@ import { XmlFormattingEditProvider } from "../xml-formatting-edit-provider"; import { XmlFormattingOptionsFactory } from "../xml-formatting-options"; export function formatAsXml(editor: TextEditor, edit: TextEditorEdit): void { - const xmlFormattingEditProvider = new XmlFormattingEditProvider(workspace.getConfiguration(constants.extensionPrefix), XmlFormatterFactory.getXmlFormatter()); + const xmlFormattingEditProvider = new XmlFormattingEditProvider(XmlFormatterFactory.getXmlFormatter()); const formattingOptions = { insertSpaces: editor.options.insertSpaces, tabSize: editor.options.tabSize diff --git a/src/formatting/commands/minifyXml.ts b/src/formatting/commands/minifyXml.ts index 7be0078..f75e8f3 100644 --- a/src/formatting/commands/minifyXml.ts +++ b/src/formatting/commands/minifyXml.ts @@ -12,7 +12,7 @@ export function minifyXml(editor: TextEditor, edit: TextEditorEdit): void { const xmlFormattingOptions = XmlFormattingOptionsFactory.getXmlFormattingOptions({ insertSpaces: editor.options.insertSpaces, tabSize: editor.options.tabSize - }, editor.document.eol); + }, editor.document); const endPosition = editor.document.lineAt(editor.document.lineCount - 1).rangeIncludingLineBreak.end; const range = new Range(editor.document.positionAt(0), endPosition); diff --git a/src/formatting/xml-formatter.ts b/src/formatting/xml-formatter.ts index b87b2b1..ddfa361 100644 --- a/src/formatting/xml-formatter.ts +++ b/src/formatting/xml-formatter.ts @@ -1,5 +1,6 @@ import { workspace } from "vscode"; +import { Configuration } from "../common"; import * as constants from "../constants"; import { ClassicXmlFormatter } from "./formatters/classic-xml-formatter"; import { V2XmlFormatter } from "./formatters/v2-xml-formatter"; @@ -19,7 +20,7 @@ export class XmlFormatterFactory { return XmlFormatterFactory._xmlFormatter; } - const xmlFormatterImplementationSetting = workspace.getConfiguration(constants.extensionPrefix).get("xmlFormatterImplementation"); + const xmlFormatterImplementationSetting = Configuration.xmlFormatterImplementation; let xmlFormatterImplementation: XmlFormatter; switch (xmlFormatterImplementationSetting) { diff --git a/src/formatting/xml-formatting-edit-provider.ts b/src/formatting/xml-formatting-edit-provider.ts index 2fd9007..6a7f9f2 100644 --- a/src/formatting/xml-formatting-edit-provider.ts +++ b/src/formatting/xml-formatting-edit-provider.ts @@ -1,7 +1,7 @@ import { workspace } from "vscode"; import { CancellationToken, DocumentFormattingEditProvider, DocumentRangeFormattingEditProvider, EndOfLine, - FormattingOptions, ProviderResult, Range, TextDocument, TextEdit, WorkspaceConfiguration + FormattingOptions, ProviderResult, Range, TextDocument, TextEdit } from "vscode"; import * as constants from "../constants"; @@ -11,7 +11,6 @@ import { XmlFormattingOptionsFactory } from "./xml-formatting-options"; export class XmlFormattingEditProvider implements DocumentFormattingEditProvider, DocumentRangeFormattingEditProvider { constructor( - public workspaceConfiguration: WorkspaceConfiguration, public xmlFormatter: XmlFormatter ) { } @@ -23,12 +22,9 @@ export class XmlFormattingEditProvider implements DocumentFormattingEditProvider } provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): ProviderResult { - // override global configuration (issue #128) - this.workspaceConfiguration = workspace.getConfiguration(constants.extensionPrefix, document.uri); - let xml = document.getText(range); - xml = this.xmlFormatter.formatXml(xml, XmlFormattingOptionsFactory.getXmlFormattingOptions(options, document.eol)); + xml = this.xmlFormatter.formatXml(xml, XmlFormattingOptionsFactory.getXmlFormattingOptions(options, document)); return [ TextEdit.replace(range, xml) ]; } diff --git a/src/formatting/xml-formatting-options.ts b/src/formatting/xml-formatting-options.ts index 4e37c24..bcfdffd 100644 --- a/src/formatting/xml-formatting-options.ts +++ b/src/formatting/xml-formatting-options.ts @@ -1,6 +1,6 @@ -import { workspace } from "vscode"; -import { EndOfLine, FormattingOptions } from "vscode"; +import { EndOfLine, FormattingOptions, TextDocument } from "vscode"; +import { Configuration } from "../common"; import * as constants from "../constants"; export interface XmlFormattingOptions { @@ -12,15 +12,13 @@ export interface XmlFormattingOptions { } export class XmlFormattingOptionsFactory { - static getXmlFormattingOptions(formattingOptions: FormattingOptions, eol: EndOfLine): XmlFormattingOptions { - const config = workspace.getConfiguration(constants.extensionPrefix); - + static getXmlFormattingOptions(formattingOptions: FormattingOptions, document: TextDocument): XmlFormattingOptions { return { editorOptions: formattingOptions, - newLine: (eol === EndOfLine.CRLF) ? "\r\n" : "\n", - removeCommentsOnMinify: config.get(constants.configKeys.removeCommentsOnMinify), - splitAttributesOnFormat: config.get(constants.configKeys.splitAttributesOnFormat), - splitXmlnsOnFormat: config.get(constants.configKeys.splitXmlnsOnFormat) + newLine: (document.eol === EndOfLine.CRLF) ? "\r\n" : "\n", + 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 f79205e..5986d6d 100644 --- a/src/tree-view/xml-tree-data-provider.ts +++ b/src/tree-view/xml-tree-data-provider.ts @@ -1,22 +1,20 @@ import { commands, window, workspace } from "vscode"; import { Event, EventEmitter, ExtensionContext, Position, TextEditor, TreeDataProvider, - TreeItem, TreeItemCollapsibleState, WorkspaceConfiguration + TreeItem, TreeItemCollapsibleState } from "vscode"; import * as path from "path"; import { DOMParser } from "xmldom"; +import { Configuration } from "../common"; import * as constants from "../constants"; export class XmlTreeDataProvider implements TreeDataProvider { - private _config: WorkspaceConfiguration; private _onDidChangeTreeData: EventEmitter = new EventEmitter(); private _xmlDocument: Document; constructor(private _context: ExtensionContext) { - this._config = workspace.getConfiguration(constants.extensionPrefix); - window.onDidChangeActiveTextEditor(() => { this._refreshTree(); }); @@ -33,8 +31,8 @@ export class XmlTreeDataProvider implements TreeDataProvider { } getTreeItem(element: Node): TreeItem | Thenable { - const enableMetadata = this._config.get(constants.configKeys.enableXmlTreeViewMetadata); - const enableSync = this._config.get(constants.configKeys.enableXmlTreeViewCursorSync); + const enableMetadata = Configuration.enableXmlTreeViewMetadata; + const enableSync = Configuration.enableXmlTreeViewCursorSync; const treeItem = new TreeItem(element.localName); @@ -208,7 +206,7 @@ export class XmlTreeDataProvider implements TreeDataProvider { return; } - const enableTreeView = this._config.get(constants.configKeys.enableXmlTreeView, true); + const enableTreeView = Configuration.enableXmlTreeView; commands.executeCommand(constants.nativeCommands.setContext, constants.contextKeys.xmlTreeViewEnabled, enableTreeView); diff --git a/src/xpath/commands/evaluateXPath.ts b/src/xpath/commands/evaluateXPath.ts index a22d10a..bc22d97 100644 --- a/src/xpath/commands/evaluateXPath.ts +++ b/src/xpath/commands/evaluateXPath.ts @@ -1,7 +1,7 @@ -import { window, workspace } from "vscode"; +import { window } from "vscode"; import { TextEditor, TextEditorEdit, ViewColumn } from "vscode"; -import { ExtensionState } from "../../common"; +import { Configuration, ExtensionState } from "../../common"; import * as constants from "../../constants"; import { EvaluatorResult, EvaluatorResultType, XPathEvaluator } from "../xpath-evaluator"; @@ -17,13 +17,11 @@ class HistoricQuery { } export async function evaluateXPath(editor: TextEditor, edit: TextEditorEdit): Promise { - const config = workspace.getConfiguration(constants.extensionPrefix); - // if there is no workspace, we will track queries in the global Memento const memento = ExtensionState.workspace || ExtensionState.global; // get the xpath persistence setting - const persistQueries = config.get(constants.configKeys.persistXPathQuery, true); + 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 @@ -49,7 +47,7 @@ export async function evaluateXPath(editor: TextEditor, edit: TextEditorEdit): P return; } - const ignoreDefaultNamespace = config.get(constants.configKeys.ignoreDefaultNamespace, true); + 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 a209e3d..da61812 100644 --- a/src/xquery-execution/commands/executeXQuery.ts +++ b/src/xquery-execution/commands/executeXQuery.ts @@ -4,10 +4,9 @@ import { Disposable, Range, TextEditor, TextEditorEdit, Uri } from "vscode"; import * as constants from "../../constants"; import { ChildProcess } from "../child-process"; +import { Configuration } from "../../common"; export async function executeXQuery(editor: TextEditor, edit: TextEditorEdit): Promise { - const config = workspace.getConfiguration(constants.extensionPrefix); - // this disposable will be used for creating status bar messages let disposable: Disposable; @@ -16,8 +15,8 @@ export async function executeXQuery(editor: TextEditor, edit: TextEditorEdit): P return; } - const executable = config.get(constants.configKeys.xqueryExecutionEngine, null); - let args = config.get(constants.configKeys.xqueryExecutionArguments, []); + 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"); @@ -32,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 = config.get(constants.configKeys.xqueryExecutionInputSearchPattern); - const inputLimit = config.get(constants.configKeys.xqueryExecutionInputLimit); + const searchPattern = Configuration.xqueryExecutionInputSearchPattern; + const inputLimit = Configuration.xqueryExecutionInputLimit; const files = await workspace.findFiles(searchPattern, "", inputLimit);