Merge pull request #250 from DotJoshJohnson/release-2.4.0
Release 2.4.0
This commit is contained in:
commit
c6eff26569
@ -1,10 +1,7 @@
|
|||||||
{
|
{
|
||||||
"comments": {
|
"comments": {
|
||||||
"lineComment": "//",
|
"lineComment": ["(:", ":)"],
|
||||||
"blockComment": [
|
"blockComment": [ "(:~", "~:)"]
|
||||||
"/*",
|
|
||||||
"*/"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"brackets": [
|
"brackets": [
|
||||||
[
|
[
|
||||||
|
@ -768,7 +768,7 @@
|
|||||||
<key>doublequotedString</key>
|
<key>doublequotedString</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>begin</key>
|
<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>
|
<key>beginCaptures</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>0</key>
|
<key>0</key>
|
||||||
@ -929,7 +929,7 @@
|
|||||||
<key>singlequotedString</key>
|
<key>singlequotedString</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>begin</key>
|
<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>
|
<key>beginCaptures</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>0</key>
|
<key>0</key>
|
||||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "xml",
|
"name": "xml",
|
||||||
"version": "2.0.0-preview.2",
|
"version": "2.3.2",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
20
package.json
20
package.json
@ -35,6 +35,8 @@
|
|||||||
"onCommand:xmlTools.evaluateXPath",
|
"onCommand:xmlTools.evaluateXPath",
|
||||||
"onCommand:xmlTools.executeXQuery",
|
"onCommand:xmlTools.executeXQuery",
|
||||||
"onCommand:xmlTools.formatAsXml",
|
"onCommand:xmlTools.formatAsXml",
|
||||||
|
"onCommand:xmlTools.textToXml",
|
||||||
|
"onCommand:xmlTools.xmlToText",
|
||||||
"onCommand:xmlTools.minifyXml",
|
"onCommand:xmlTools.minifyXml",
|
||||||
"onLanguage:xml",
|
"onLanguage:xml",
|
||||||
"onLanguage:xquery",
|
"onLanguage:xquery",
|
||||||
@ -55,6 +57,14 @@
|
|||||||
"command": "xmlTools.formatAsXml",
|
"command": "xmlTools.formatAsXml",
|
||||||
"title": "XML Tools: Format as XML"
|
"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",
|
"command": "xmlTools.getCurrentXPath",
|
||||||
"title": "XML Tools: Get Current XPath"
|
"title": "XML Tools: Get Current XPath"
|
||||||
@ -183,6 +193,16 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"languages": [
|
"languages": [
|
||||||
|
{
|
||||||
|
"id": "xml",
|
||||||
|
"extensions": [
|
||||||
|
".config",
|
||||||
|
".csproj",
|
||||||
|
".xml",
|
||||||
|
".xsd",
|
||||||
|
".xsl"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "xquery",
|
"id": "xquery",
|
||||||
"aliases": [
|
"aliases": [
|
||||||
|
@ -2,6 +2,8 @@ export namespace commands {
|
|||||||
export const evaluateXPath = "xmlTools.evaluateXPath";
|
export const evaluateXPath = "xmlTools.evaluateXPath";
|
||||||
export const executeXQuery = "xmlTools.executeXQuery";
|
export const executeXQuery = "xmlTools.executeXQuery";
|
||||||
export const formatAsXml = "xmlTools.formatAsXml";
|
export const formatAsXml = "xmlTools.formatAsXml";
|
||||||
|
export const xmlToText = "xmlTools.xmlToText";
|
||||||
|
export const textToXml = "xmlTools.textToXml";
|
||||||
export const getCurrentXPath = "xmlTools.getCurrentXPath";
|
export const getCurrentXPath = "xmlTools.getCurrentXPath";
|
||||||
export const minifyXml = "xmlTools.minifyXml";
|
export const minifyXml = "xmlTools.minifyXml";
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import {
|
import {
|
||||||
commands, languages, window, workspace, ExtensionContext, Memento,
|
commands, languages, window, workspace, ExtensionContext, Memento,
|
||||||
TextEditor, TextEditorSelectionChangeEvent, TextEditorSelectionChangeKind
|
TextEditor, TextEditorSelectionChangeEvent, TextEditorSelectionChangeKind, DiagnosticCollection
|
||||||
} from "vscode";
|
} from "vscode";
|
||||||
|
|
||||||
import { createDocumentSelector, ExtensionState, Configuration } from "./common";
|
import { createDocumentSelector, ExtensionState, Configuration } from "./common";
|
||||||
import { XQueryCompletionItemProvider } from "./completion";
|
import { XQueryCompletionItemProvider } from "./completion";
|
||||||
import { XmlFormatterFactory, XmlFormattingEditProvider } from "./formatting";
|
import { XmlFormatterFactory, XmlFormattingEditProvider } from "./formatting";
|
||||||
import { formatAsXml, minifyXml } from "./formatting/commands";
|
import { formatAsXml, minifyXml, xmlToText, textToXml } from "./formatting/commands";
|
||||||
import { XQueryLinter } from "./linting";
|
import { XQueryLinter } from "./linting";
|
||||||
import { XmlTreeDataProvider } from "./tree-view";
|
import { XmlTreeDataProvider } from "./tree-view";
|
||||||
import { evaluateXPath, getCurrentXPath } from "./xpath/commands";
|
import { evaluateXPath, getCurrentXPath } from "./xpath/commands";
|
||||||
@ -14,6 +14,8 @@ import { executeXQuery } from "./xquery-execution/commands";
|
|||||||
|
|
||||||
import * as constants from "./constants";
|
import * as constants from "./constants";
|
||||||
|
|
||||||
|
let diagnosticCollectionXQuery: DiagnosticCollection;
|
||||||
|
|
||||||
export function activate(context: ExtensionContext) {
|
export function activate(context: ExtensionContext) {
|
||||||
ExtensionState.configure(context);
|
ExtensionState.configure(context);
|
||||||
|
|
||||||
@ -30,13 +32,17 @@ export function activate(context: ExtensionContext) {
|
|||||||
|
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
commands.registerTextEditorCommand(constants.commands.formatAsXml, formatAsXml),
|
commands.registerTextEditorCommand(constants.commands.formatAsXml, formatAsXml),
|
||||||
|
commands.registerTextEditorCommand(constants.commands.xmlToText, xmlToText),
|
||||||
|
commands.registerTextEditorCommand(constants.commands.textToXml, textToXml),
|
||||||
commands.registerTextEditorCommand(constants.commands.minifyXml, minifyXml),
|
commands.registerTextEditorCommand(constants.commands.minifyXml, minifyXml),
|
||||||
languages.registerDocumentFormattingEditProvider(xmlXsdDocSelector, xmlFormattingEditProvider),
|
languages.registerDocumentFormattingEditProvider(xmlXsdDocSelector, xmlFormattingEditProvider),
|
||||||
languages.registerDocumentRangeFormattingEditProvider(xmlXsdDocSelector, xmlFormattingEditProvider)
|
languages.registerDocumentRangeFormattingEditProvider(xmlXsdDocSelector, xmlFormattingEditProvider)
|
||||||
);
|
);
|
||||||
|
|
||||||
/* Linting Features */
|
/* Linting Features */
|
||||||
|
diagnosticCollectionXQuery = languages.createDiagnosticCollection(constants.diagnosticCollections.xquery);
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
|
diagnosticCollectionXQuery,
|
||||||
window.onDidChangeActiveTextEditor(_handleChangeActiveTextEditor),
|
window.onDidChangeActiveTextEditor(_handleChangeActiveTextEditor),
|
||||||
window.onDidChangeTextEditorSelection(_handleChangeTextEditorSelection)
|
window.onDidChangeTextEditorSelection(_handleChangeTextEditorSelection)
|
||||||
);
|
);
|
||||||
@ -85,9 +91,7 @@ function _handleContextChange(editor: TextEditor): void {
|
|||||||
|
|
||||||
switch (editor.document.languageId) {
|
switch (editor.document.languageId) {
|
||||||
case constants.languageIds.xquery:
|
case constants.languageIds.xquery:
|
||||||
languages
|
diagnosticCollectionXQuery.set(editor.document.uri, new XQueryLinter().lint(editor.document.getText()));
|
||||||
.createDiagnosticCollection(constants.diagnosticCollections.xquery)
|
|
||||||
.set(editor.document.uri, new XQueryLinter().lint(editor.document.getText()));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
export * from "./formatAsXml";
|
export * from "./formatAsXml";
|
||||||
export * from "./minifyXml";
|
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+(?=[^\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, "\" "); // 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, " ");
|
return match.replace(/\s+/g, " ");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ export class V2XmlFormatter implements XmlFormatter {
|
|||||||
|
|
||||||
let output = "";
|
let output = "";
|
||||||
|
|
||||||
let indentLevel = 0;
|
let indentLevel = options.initialIndentLevel || 0;
|
||||||
let attributeQuote = "";
|
let attributeQuote = "";
|
||||||
let lineBreakSpree = false;
|
let lineBreakSpree = false;
|
||||||
let lastWordCharacter: string | undefined;
|
let lastWordCharacter: string | undefined;
|
||||||
|
@ -22,10 +22,43 @@ export class XmlFormattingEditProvider implements DocumentFormattingEditProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): ProviderResult<TextEdit[]> {
|
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;
|
removeCommentsOnMinify: boolean;
|
||||||
splitAttributesOnFormat: boolean;
|
splitAttributesOnFormat: boolean;
|
||||||
splitXmlnsOnFormat: boolean;
|
splitXmlnsOnFormat: boolean;
|
||||||
|
initialIndentLevel?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class XmlFormattingOptionsFactory {
|
export class XmlFormattingOptionsFactory {
|
||||||
@ -20,7 +21,8 @@ export class XmlFormattingOptionsFactory {
|
|||||||
newLine: (document.eol === EndOfLine.CRLF) ? "\r\n" : "\n",
|
newLine: (document.eol === EndOfLine.CRLF) ? "\r\n" : "\n",
|
||||||
removeCommentsOnMinify: Configuration.removeCommentsOnMinify(document.uri),
|
removeCommentsOnMinify: Configuration.removeCommentsOnMinify(document.uri),
|
||||||
splitAttributesOnFormat: Configuration.splitAttributesOnFormat(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");
|
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…
Reference in New Issue
Block a user