Merge pull request #250 from DotJoshJohnson/release-2.4.0
Release 2.4.0
This commit is contained in:
		
						commit
						c6eff26569
					
				
					 15 changed files with 175 additions and 22 deletions
				
			
		| 
						 | 
				
			
			@ -1,10 +1,7 @@
 | 
			
		|||
{
 | 
			
		||||
    "comments": {
 | 
			
		||||
        "lineComment": "//",
 | 
			
		||||
        "blockComment": [
 | 
			
		||||
            "/*",
 | 
			
		||||
            "*/"
 | 
			
		||||
        ]
 | 
			
		||||
        "lineComment": ["(:", ":)"],
 | 
			
		||||
        "blockComment": [ "(:~", "~:)"]
 | 
			
		||||
    },
 | 
			
		||||
    "brackets": [
 | 
			
		||||
        [
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -768,7 +768,7 @@
 | 
			
		|||
		<key>doublequotedString</key>
 | 
			
		||||
		<dict>
 | 
			
		||||
			<key>begin</key>
 | 
			
		||||
			<string>(?<![-_a-zA-Z0-9:]>)\s*"(?!\s*</[-_a-zA-Z0-9:])</string>
 | 
			
		||||
			<string>(?<![-_a-zA-Z0-9:'"]>)\s*"(?![\w\s()']*</[-_a-zA-Z0-9:])</string>
 | 
			
		||||
			<key>beginCaptures</key>
 | 
			
		||||
			<dict>
 | 
			
		||||
				<key>0</key>
 | 
			
		||||
| 
						 | 
				
			
			@ -929,7 +929,7 @@
 | 
			
		|||
		<key>singlequotedString</key>
 | 
			
		||||
		<dict>
 | 
			
		||||
			<key>begin</key>
 | 
			
		||||
			<string>(?<![-_a-zA-Z0-9:]>)\s*'(?!\s*</[-_a-zA-Z0-9:])</string>
 | 
			
		||||
			<string>(?<![-_a-zA-Z0-9:'"]>)\s*'(?![\w\s()"]*</[-_a-zA-Z0-9:])</string>
 | 
			
		||||
			<key>beginCaptures</key>
 | 
			
		||||
			<dict>
 | 
			
		||||
				<key>0</key>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
{
 | 
			
		||||
    "name": "xml",
 | 
			
		||||
    "version": "2.0.0-preview.2",
 | 
			
		||||
    "version": "2.3.2",
 | 
			
		||||
    "lockfileVersion": 1,
 | 
			
		||||
    "requires": true,
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										20
									
								
								package.json
									
										
									
									
									
								
							
							
						
						
									
										20
									
								
								package.json
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -35,6 +35,8 @@
 | 
			
		|||
        "onCommand:xmlTools.evaluateXPath",
 | 
			
		||||
        "onCommand:xmlTools.executeXQuery",
 | 
			
		||||
        "onCommand:xmlTools.formatAsXml",
 | 
			
		||||
        "onCommand:xmlTools.textToXml",
 | 
			
		||||
        "onCommand:xmlTools.xmlToText",
 | 
			
		||||
        "onCommand:xmlTools.minifyXml",
 | 
			
		||||
        "onLanguage:xml",
 | 
			
		||||
        "onLanguage:xquery",
 | 
			
		||||
| 
						 | 
				
			
			@ -55,6 +57,14 @@
 | 
			
		|||
                "command": "xmlTools.formatAsXml",
 | 
			
		||||
                "title": "XML Tools: Format as XML"
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "command": "xmlTools.textToXml",
 | 
			
		||||
                "title": "XML Tools: Convert text to XML (<> -> <>)"
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "command": "xmlTools.xmlToText",
 | 
			
		||||
                "title": "XML Tools: Convert XML to text  (<> -> <>)"
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "command": "xmlTools.getCurrentXPath",
 | 
			
		||||
                "title": "XML Tools: Get Current XPath"
 | 
			
		||||
| 
						 | 
				
			
			@ -183,6 +193,16 @@
 | 
			
		|||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "languages": [
 | 
			
		||||
            {
 | 
			
		||||
                "id": "xml",
 | 
			
		||||
                "extensions": [
 | 
			
		||||
                    ".config",
 | 
			
		||||
                    ".csproj",
 | 
			
		||||
                    ".xml",
 | 
			
		||||
                    ".xsd",
 | 
			
		||||
                    ".xsl"
 | 
			
		||||
                ]
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "id": "xquery",
 | 
			
		||||
                "aliases": [
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,8 @@ export namespace commands {
 | 
			
		|||
    export const evaluateXPath = "xmlTools.evaluateXPath";
 | 
			
		||||
    export const executeXQuery = "xmlTools.executeXQuery";
 | 
			
		||||
    export const formatAsXml = "xmlTools.formatAsXml";
 | 
			
		||||
    export const xmlToText = "xmlTools.xmlToText";
 | 
			
		||||
    export const textToXml = "xmlTools.textToXml";
 | 
			
		||||
    export const getCurrentXPath = "xmlTools.getCurrentXPath";
 | 
			
		||||
    export const minifyXml = "xmlTools.minifyXml";
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,12 +1,12 @@
 | 
			
		|||
import {
 | 
			
		||||
    commands, languages, window, workspace, ExtensionContext, Memento,
 | 
			
		||||
    TextEditor, TextEditorSelectionChangeEvent, TextEditorSelectionChangeKind
 | 
			
		||||
    TextEditor, TextEditorSelectionChangeEvent, TextEditorSelectionChangeKind, DiagnosticCollection
 | 
			
		||||
    } from "vscode";
 | 
			
		||||
 | 
			
		||||
import { createDocumentSelector, ExtensionState, Configuration } from "./common";
 | 
			
		||||
import { XQueryCompletionItemProvider } from "./completion";
 | 
			
		||||
import { XmlFormatterFactory, XmlFormattingEditProvider } from "./formatting";
 | 
			
		||||
import { formatAsXml, minifyXml } from "./formatting/commands";
 | 
			
		||||
import { formatAsXml, minifyXml, xmlToText, textToXml } from "./formatting/commands";
 | 
			
		||||
import { XQueryLinter } from "./linting";
 | 
			
		||||
import { XmlTreeDataProvider } from "./tree-view";
 | 
			
		||||
import { evaluateXPath, getCurrentXPath } from "./xpath/commands";
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +14,8 @@ import { executeXQuery } from "./xquery-execution/commands";
 | 
			
		|||
 | 
			
		||||
import * as constants from "./constants";
 | 
			
		||||
 | 
			
		||||
let diagnosticCollectionXQuery: DiagnosticCollection;
 | 
			
		||||
 | 
			
		||||
export function activate(context: ExtensionContext) {
 | 
			
		||||
    ExtensionState.configure(context);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -30,13 +32,17 @@ export function activate(context: ExtensionContext) {
 | 
			
		|||
 | 
			
		||||
    context.subscriptions.push(
 | 
			
		||||
        commands.registerTextEditorCommand(constants.commands.formatAsXml, formatAsXml),
 | 
			
		||||
        commands.registerTextEditorCommand(constants.commands.xmlToText, xmlToText),
 | 
			
		||||
        commands.registerTextEditorCommand(constants.commands.textToXml, textToXml),
 | 
			
		||||
        commands.registerTextEditorCommand(constants.commands.minifyXml, minifyXml),
 | 
			
		||||
        languages.registerDocumentFormattingEditProvider(xmlXsdDocSelector, xmlFormattingEditProvider),
 | 
			
		||||
        languages.registerDocumentRangeFormattingEditProvider(xmlXsdDocSelector, xmlFormattingEditProvider)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /* Linting Features */
 | 
			
		||||
    diagnosticCollectionXQuery = languages.createDiagnosticCollection(constants.diagnosticCollections.xquery);
 | 
			
		||||
    context.subscriptions.push(
 | 
			
		||||
        diagnosticCollectionXQuery,
 | 
			
		||||
        window.onDidChangeActiveTextEditor(_handleChangeActiveTextEditor),
 | 
			
		||||
        window.onDidChangeTextEditorSelection(_handleChangeTextEditorSelection)
 | 
			
		||||
    );
 | 
			
		||||
| 
						 | 
				
			
			@ -85,9 +91,7 @@ function _handleContextChange(editor: TextEditor): void {
 | 
			
		|||
 | 
			
		||||
    switch (editor.document.languageId) {
 | 
			
		||||
        case constants.languageIds.xquery:
 | 
			
		||||
            languages
 | 
			
		||||
                .createDiagnosticCollection(constants.diagnosticCollections.xquery)
 | 
			
		||||
                .set(editor.document.uri, new XQueryLinter().lint(editor.document.getText()));
 | 
			
		||||
      diagnosticCollectionXQuery.set(editor.document.uri, new XQueryLinter().lint(editor.document.getText()));
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1,4 @@
 | 
			
		|||
export * from "./formatAsXml";
 | 
			
		||||
export * from "./minifyXml";
 | 
			
		||||
export * from "./xmlToText";
 | 
			
		||||
export * from "./textToXml";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										26
									
								
								src/formatting/commands/textToXml.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/formatting/commands/textToXml.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
import { workspace } from "vscode";
 | 
			
		||||
import { ProviderResult, Range, TextEdit, TextEditor, Selection } from "vscode";
 | 
			
		||||
 | 
			
		||||
import { NativeCommands } from "../../common";
 | 
			
		||||
import * as constants from "../../constants";
 | 
			
		||||
 | 
			
		||||
import { XmlFormatterFactory } from "../xml-formatter";
 | 
			
		||||
import { XmlFormattingEditProvider } from "../xml-formatting-edit-provider";
 | 
			
		||||
import { XmlFormattingOptionsFactory } from "../xml-formatting-options";
 | 
			
		||||
 | 
			
		||||
export function textToXml(textEditor: TextEditor): void {
 | 
			
		||||
    textEditor.edit(textEdit => {
 | 
			
		||||
        const selections = textEditor.selections;
 | 
			
		||||
        selections.forEach(selection => {
 | 
			
		||||
            if (selection.isEmpty) {
 | 
			
		||||
                selection = new Selection(
 | 
			
		||||
                    textEditor.document.positionAt(0),
 | 
			
		||||
                    textEditor.document.positionAt(textEditor.document.getText().length)
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
            const txt = textEditor.document.getText(new Range(selection.start, selection.end));
 | 
			
		||||
            const transformed = txt.replace(/</g, "<").replace(/>/g, ">");
 | 
			
		||||
            textEdit.replace(selection, transformed);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								src/formatting/commands/xmlToText.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/formatting/commands/xmlToText.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
import { workspace } from "vscode";
 | 
			
		||||
import { ProviderResult, Range, TextEdit, TextEditor, Selection } from "vscode";
 | 
			
		||||
 | 
			
		||||
import { NativeCommands } from "../../common";
 | 
			
		||||
import * as constants from "../../constants";
 | 
			
		||||
 | 
			
		||||
import { XmlFormatterFactory } from "../xml-formatter";
 | 
			
		||||
import { XmlFormattingEditProvider } from "../xml-formatting-edit-provider";
 | 
			
		||||
import { XmlFormattingOptionsFactory } from "../xml-formatting-options";
 | 
			
		||||
 | 
			
		||||
export function xmlToText(textEditor: TextEditor): void {
 | 
			
		||||
    textEditor.edit(textEdit => {
 | 
			
		||||
        const selections = textEditor.selections;
 | 
			
		||||
        selections.forEach(selection => {
 | 
			
		||||
            if (selection.isEmpty) {
 | 
			
		||||
                selection = new Selection(
 | 
			
		||||
                    textEditor.document.positionAt(0),
 | 
			
		||||
                    textEditor.document.positionAt(textEditor.document.getText().length)
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
            const txt = textEditor.document.getText(new Range(selection.start, selection.end));
 | 
			
		||||
            const transformed = txt.replace(/</g, "<").replace(/>/g, ">");
 | 
			
		||||
            textEdit.replace(selection, transformed);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ export class V2XmlFormatter implements XmlFormatter {
 | 
			
		|||
        xml = xml.replace(/"\s+(?=[^\s]+=)/g, "\" "); // spaces between attributes
 | 
			
		||||
        xml = xml.replace(/"\s+(?=>)/g, "\""); // spaces between the last attribute and tag close (>)
 | 
			
		||||
        xml = xml.replace(/"\s+(?=\/>)/g, "\" "); // spaces between the last attribute and tag close (/>)
 | 
			
		||||
        xml = xml.replace(/[^ <>="]\s+[^ <>="]+=/g, (match: string) => { // spaces between the node name and the first attribute
 | 
			
		||||
        xml = xml.replace(/(?!<!\[CDATA\[)[^ <>="]\s+[^ <>="]+=(?![^<]*?\]\]>)/g, (match: string) => { // spaces between the node name and the first attribute
 | 
			
		||||
            return match.replace(/\s+/g, " ");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -29,7 +29,7 @@ export class V2XmlFormatter implements XmlFormatter {
 | 
			
		|||
 | 
			
		||||
        let output = "";
 | 
			
		||||
 | 
			
		||||
        let indentLevel = 0;
 | 
			
		||||
        let indentLevel = options.initialIndentLevel || 0;
 | 
			
		||||
        let attributeQuote = "";
 | 
			
		||||
        let lineBreakSpree = false;
 | 
			
		||||
        let lastWordCharacter: string | undefined;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,10 +22,43 @@ export class XmlFormattingEditProvider implements DocumentFormattingEditProvider
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): ProviderResult<TextEdit[]> {
 | 
			
		||||
        let xml = document.getText(range);
 | 
			
		||||
        const allXml = document.getText();
 | 
			
		||||
        let selectedXml = document.getText(range);
 | 
			
		||||
        const extFormattingOptions = XmlFormattingOptionsFactory.getXmlFormattingOptions(options, document);
 | 
			
		||||
 | 
			
		||||
        xml = this.xmlFormatter.formatXml(xml, XmlFormattingOptionsFactory.getXmlFormattingOptions(options, document));
 | 
			
		||||
        const selectionStartOffset = document.offsetAt(range.start);
 | 
			
		||||
        let tabCount = 0;
 | 
			
		||||
        let spaceCount = 0;
 | 
			
		||||
 | 
			
		||||
        return [ TextEdit.replace(range, xml) ];
 | 
			
		||||
        for (let i = (selectionStartOffset - 1); i >= 0; i--) {
 | 
			
		||||
            const cc = allXml.charAt(i);
 | 
			
		||||
 | 
			
		||||
            if (/\t/.test(cc)) {
 | 
			
		||||
                tabCount++;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            else if (/ /.test(cc)) {
 | 
			
		||||
                spaceCount++;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            else {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (options.insertSpaces) {
 | 
			
		||||
            extFormattingOptions.initialIndentLevel = Math.ceil(spaceCount / (options.tabSize || 1));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        else {
 | 
			
		||||
            extFormattingOptions.initialIndentLevel = tabCount;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        selectedXml = this.xmlFormatter.formatXml(selectedXml, extFormattingOptions);
 | 
			
		||||
 | 
			
		||||
        // we need to remove the leading whitespace because the formatter will add an indent before the first element
 | 
			
		||||
        selectedXml = selectedXml.replace(/^\s+/, "");
 | 
			
		||||
 | 
			
		||||
        return [TextEdit.replace(range, selectedXml)];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ export interface XmlFormattingOptions {
 | 
			
		|||
    removeCommentsOnMinify: boolean;
 | 
			
		||||
    splitAttributesOnFormat: boolean;
 | 
			
		||||
    splitXmlnsOnFormat: boolean;
 | 
			
		||||
    initialIndentLevel?: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class XmlFormattingOptionsFactory {
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +21,8 @@ export class XmlFormattingOptionsFactory {
 | 
			
		|||
            newLine: (document.eol === EndOfLine.CRLF) ? "\r\n" : "\n",
 | 
			
		||||
            removeCommentsOnMinify: Configuration.removeCommentsOnMinify(document.uri),
 | 
			
		||||
            splitAttributesOnFormat: Configuration.splitAttributesOnFormat(document.uri),
 | 
			
		||||
            splitXmlnsOnFormat: Configuration.splitXmlnsOnFormat(document.uri)
 | 
			
		||||
            splitXmlnsOnFormat: Configuration.splitXmlnsOnFormat(document.uri),
 | 
			
		||||
            initialIndentLevel: 0
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -92,6 +92,9 @@ describe("V2XmlFormatter", () => {
 | 
			
		|||
            testFormatter(xmlFormatter, options, "issue-200");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it("should not remove spaces between the node name and the first attribute within CDATA", () => {
 | 
			
		||||
            testFormatter(xmlFormatter, options, "issue-227");
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										19
									
								
								src/test/test-data/issue-227.formatted.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/test/test-data/issue-227.formatted.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
<Job>
 | 
			
		||||
    <SQLQuery test="">
 | 
			
		||||
        <SQLSelect Test="test" test="test">
 | 
			
		||||
            <![CDATA[
 | 
			
		||||
select
 | 
			
		||||
*
 | 
			
		||||
from test
 | 
			
		||||
where
 | 
			
		||||
aaa.aaa='AAA' and 
 | 
			
		||||
isnull(BBB.BBB,0)=0 and
 | 
			
		||||
isnull(CCTestC.CCC,0)=1 and
 | 
			
		||||
DDD.DDD is null and
 | 
			
		||||
exists (select 1 from EEE where EEE.EEE=EEE.EEE and EEE is null) and
 | 
			
		||||
exists (select 1 from FFF where FFF.FFF=FFF.FFF) and
 | 
			
		||||
'{GGG}' like '%'+GGG.GGG+'%'
 | 
			
		||||
]]>
 | 
			
		||||
        </SQLSelect>
 | 
			
		||||
    </SQLQuery>
 | 
			
		||||
</Job>
 | 
			
		||||
							
								
								
									
										19
									
								
								src/test/test-data/issue-227.unformatted.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/test/test-data/issue-227.unformatted.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
<Job>
 | 
			
		||||
  <SQLQuery      test="">
 | 
			
		||||
    <SQLSelect    Test="test"     test="test">
 | 
			
		||||
             <![CDATA[
 | 
			
		||||
select
 | 
			
		||||
*
 | 
			
		||||
from test
 | 
			
		||||
where
 | 
			
		||||
aaa.aaa='AAA' and 
 | 
			
		||||
isnull(BBB.BBB,0)=0 and
 | 
			
		||||
isnull(CCTestC.CCC,0)=1 and
 | 
			
		||||
DDD.DDD is null and
 | 
			
		||||
exists (select 1 from EEE where EEE.EEE=EEE.EEE and EEE is null) and
 | 
			
		||||
exists (select 1 from FFF where FFF.FFF=FFF.FFF) and
 | 
			
		||||
'{GGG}' like '%'+GGG.GGG+'%'
 | 
			
		||||
]]>
 | 
			
		||||
    </SQLSelect>
 | 
			
		||||
	</SQLQuery>
 | 
			
		||||
</Job>
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue