Merge pull request #250 from DotJoshJohnson/release-2.4.0

Release 2.4.0
This commit is contained in:
Josh Johnson 2018-12-14 11:04:51 -05:00 committed by GitHub
commit c6eff26569
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 175 additions and 22 deletions

View File

@ -1,10 +1,7 @@
{
"comments": {
"lineComment": "//",
"blockComment": [
"/*",
"*/"
]
"lineComment": ["(:", ":)"],
"blockComment": [ "(:~", "~:)"]
},
"brackets": [
[
@ -20,4 +17,4 @@
")"
]
]
}
}

View File

@ -768,7 +768,7 @@
<key>doublequotedString</key>
<dict>
<key>begin</key>
<string>(?&lt;![-_a-zA-Z0-9:]&gt;)\s*"(?!\s*&lt;/[-_a-zA-Z0-9:])</string>
<string>(?&lt;![-_a-zA-Z0-9:'"]&gt;)\s*"(?![\w\s()']*&lt;/[-_a-zA-Z0-9:])</string>
<key>beginCaptures</key>
<dict>
<key>0</key>
@ -929,7 +929,7 @@
<key>singlequotedString</key>
<dict>
<key>begin</key>
<string>(?&lt;![-_a-zA-Z0-9:]&gt;)\s*'(?!\s*&lt;/[-_a-zA-Z0-9:])</string>
<string>(?&lt;![-_a-zA-Z0-9:'"]&gt;)\s*'(?![\w\s()"]*&lt;/[-_a-zA-Z0-9:])</string>
<key>beginCaptures</key>
<dict>
<key>0</key>

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "xml",
"version": "2.0.0-preview.2",
"version": "2.3.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -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 (&lt;&gt; -> <>)"
},
{
"command": "xmlTools.xmlToText",
"title": "XML Tools: Convert XML to text (<> -> &lt;&gt;)"
},
{
"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": [
@ -257,4 +277,4 @@
"xpath": "0.0.27",
"xqlint": "^0.4.1"
}
}
}

View File

@ -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";
}

View File

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

View File

@ -1,2 +1,4 @@
export * from "./formatAsXml";
export * from "./minifyXml";
export * from "./xmlToText";
export * from "./textToXml";

View 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(/&lt;/g, "<").replace(/&gt;/g, ">");
textEdit.replace(selection, transformed);
});
});
}

View 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, "&lt;").replace(/>/g, "&gt;");
textEdit.replace(selection, transformed);
});
});
}

View File

@ -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;
@ -194,7 +194,7 @@ export class V2XmlFormatter implements XmlFormatter {
&& cc === "/"
&& pc !== " "
&& options.enforcePrettySelfClosingTagOnFormat) {
output += " /";
output += " /";
}
// exiting StartTag or StartTag.StartTagName, entering Text

View File

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

View File

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

View File

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

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

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