diff --git a/packages/ast/README.md b/packages/ast/README.md
index ad828cdc..eb1dbbff 100644
--- a/packages/ast/README.md
+++ b/packages/ast/README.md
@@ -42,8 +42,8 @@ const xmlText = `
`;
-const { cst } = parse(xmlText);
-const xmlDocAst = buildAst(cst);
+const { cst, tokenVector } = parse(xmlText);
+const xmlDocAst = buildAst(cst, tokenVector);
console.log(xmlDocAst.rootElement.name); // -> note
// A Visitor allows us to invoke actions on the XML ASTNodes without worrying about
diff --git a/packages/ast/api.d.ts b/packages/ast/api.d.ts
index 1870ebf2..8989ac1a 100644
--- a/packages/ast/api.d.ts
+++ b/packages/ast/api.d.ts
@@ -1,12 +1,14 @@
+import { IToken } from "chevrotain";
import { DocumentCstNode } from "@xml-tools/parser";
/**
* Builds an XML Ast from an XML Cst.
* Can process even partial CSTs...
- *
- * @param docCst
*/
-export function buildAst(docCst: DocumentCstNode): XMLDocument;
+export function buildAst(
+ docCst: DocumentCstNode,
+ tokenVector: IToken[]
+): XMLDocument;
/**
* An Abstract Syntax Tree structure
@@ -85,6 +87,23 @@ declare interface XMLElement {
// Will not exist if any of the closing "brackets" are missing
// - e.g in a self closing element.
readonly closeBody?: XMLToken;
+
+ // Describes the range of the attributes section:
+ // This starts one character **after** the opening name token
+ // and ends one character before the open body closing '>' or self closing '/>
+ // Examples:
+ // Some content
+ // <===== attributesRange =====>
+ //
+ // <===== attributesRange =====>
+ readonly attributesRange?: SourceRange;
+
+ // Same as attributesRange except this property will be used for partially valid
+ // XMLElements when the AstBuilder cannot be certain what is the exact attributes range.
+ // - Only one of the attributeRanges properties may exist at the same time.
+ // - It is possible that in some cases it won't be possible to even guess the attributes range.
+ // In that scenario neither of the properties will exist.
+ readonly guessedAttributesRange?: SourceRange;
};
readonly position: SourcePosition;
}
@@ -114,6 +133,11 @@ declare interface XMLAttribute {
readonly position: SourcePosition;
}
+declare interface SourceRange {
+ readonly startOffset: number;
+ readonly endOffset: number;
+}
+
declare interface SourcePosition {
readonly startOffset: number;
readonly endOffset: number;
diff --git a/packages/ast/lib/build-ast.js b/packages/ast/lib/build-ast.js
index 2184e0dc..602b5213 100644
--- a/packages/ast/lib/build-ast.js
+++ b/packages/ast/lib/build-ast.js
@@ -1,5 +1,6 @@
const { BaseXmlCstVisitor } = require("@xml-tools/parser");
const {
+ last,
forEach,
reduce,
map,
@@ -8,14 +9,16 @@ const {
isEmpty,
isArray
} = require("lodash");
-
+const { findNextTextualToken } = require("@xml-tools/common");
const { getAstChildrenReflective } = require("./utils");
/**
* @param {DocumentCstNode} docCst
+ * @param {IToken[]} tokenVector
* @returns {XMLDocument}
*/
-function buildAst(docCst) {
+function buildAst(docCst, tokenVector) {
+ AstBuilder.setState({ tokenVector });
const xmlDocAst = AstBuilder.visit(docCst);
if (xmlDocAst.rootElement !== invalidSyntax) {
@@ -29,6 +32,10 @@ class CstToAstVisitor extends BaseXmlCstVisitor {
super();
}
+ setState({ tokenVector }) {
+ this.tokenVector = tokenVector;
+ }
+
visit(cstNode) {
return super.visit(cstNode, cstNode.location);
}
@@ -104,7 +111,7 @@ class CstToAstVisitor extends BaseXmlCstVisitor {
}
/**
- * @param ctx {ElementCstNode}
+ * @param ctx {ElementCtx}
* @param location {SourcePosition}
*/
element(ctx, location) {
@@ -129,49 +136,10 @@ class CstToAstVisitor extends BaseXmlCstVisitor {
astNode.textContents = textContents;
}
- if (ctx.Name !== undefined && ctx.Name[0].isInsertedInRecovery !== true) {
- const openNameToken = ctx.Name[0];
- astNode.syntax.openName = toXMLToken(openNameToken);
- const nsParts = nsToParts(openNameToken.image);
- if (nsParts !== null) {
- astNode.ns = nsParts.ns;
- astNode.name = nsParts.name;
- } else {
- astNode.name = openNameToken.image;
- }
- }
+ handleElementOpenCloseNameRanges(astNode, ctx);
+ handleElementOpenCloseBodyRanges(astNode, ctx);
+ handleElementAttributeRanges(astNode, ctx, this.tokenVector);
- if (
- ctx.END_NAME !== undefined &&
- ctx.END_NAME[0].isInsertedInRecovery !== true
- ) {
- astNode.syntax.closeName = toXMLToken(ctx.END_NAME[0]);
- }
-
- /* istanbul ignore else - Defensive Coding */
- if (exists(ctx.OPEN)) {
- let openBodyCloseTok = undefined;
- /* istanbul ignore else - Defensive Coding */
- if (exists(ctx.START_CLOSE)) {
- openBodyCloseTok = ctx.START_CLOSE[0];
- } else if (exists(ctx.SLASH_CLOSE)) {
- openBodyCloseTok = ctx.SLASH_CLOSE[0];
- }
-
- if (openBodyCloseTok !== undefined) {
- astNode.syntax.openBody = {
- ...startOfXMLToken(ctx.OPEN[0]),
- ...endOfXMLToken(openBodyCloseTok)
- };
- }
- }
-
- if (exists(ctx.SLASH_OPEN) && exists(ctx.END)) {
- astNode.syntax.closeBody = {
- ...startOfXMLToken(ctx.SLASH_OPEN[0]),
- ...endOfXMLToken(ctx.END[0])
- };
- }
setChildrenParent(astNode);
return astNode;
@@ -299,7 +267,6 @@ function updateNamespaces(element, prevNamespaces = []) {
}
/**
- *
* @param {chevrotain.IToken} token
*/
function toXMLToken(token) {
@@ -352,6 +319,98 @@ function nsToParts(text) {
*/
const invalidSyntax = null;
+/**
+ * @param {XMLElement} astNode
+ * @param {ElementCtx} ctx
+ */
+function handleElementOpenCloseNameRanges(astNode, ctx) {
+ if (ctx.Name !== undefined && ctx.Name[0].isInsertedInRecovery !== true) {
+ const openNameToken = ctx.Name[0];
+ astNode.syntax.openName = toXMLToken(openNameToken);
+ const nsParts = nsToParts(openNameToken.image);
+ if (nsParts !== null) {
+ astNode.ns = nsParts.ns;
+ astNode.name = nsParts.name;
+ } else {
+ astNode.name = openNameToken.image;
+ }
+ }
+
+ if (
+ ctx.END_NAME !== undefined &&
+ ctx.END_NAME[0].isInsertedInRecovery !== true
+ ) {
+ astNode.syntax.closeName = toXMLToken(ctx.END_NAME[0]);
+ }
+}
+
+/**
+ * @param {XMLElement} astNode
+ * @param {ElementCtx} ctx
+ */
+function handleElementOpenCloseBodyRanges(astNode, ctx) {
+ /* istanbul ignore else - Defensive Coding */
+ if (exists(ctx.OPEN)) {
+ let openBodyCloseTok = undefined;
+ /* istanbul ignore else - Defensive Coding */
+ if (exists(ctx.START_CLOSE)) {
+ openBodyCloseTok = ctx.START_CLOSE[0];
+ } else if (exists(ctx.SLASH_CLOSE)) {
+ openBodyCloseTok = ctx.SLASH_CLOSE[0];
+ }
+
+ if (openBodyCloseTok !== undefined) {
+ astNode.syntax.openBody = {
+ ...startOfXMLToken(ctx.OPEN[0]),
+ ...endOfXMLToken(openBodyCloseTok)
+ };
+ }
+
+ if (exists(ctx.SLASH_OPEN) && exists(ctx.END)) {
+ astNode.syntax.closeBody = {
+ ...startOfXMLToken(ctx.SLASH_OPEN[0]),
+ ...endOfXMLToken(ctx.END[0])
+ };
+ }
+ }
+}
+
+/**
+ * @param {XMLElement} astNode
+ * @param {ElementCtx} ctx
+ * @param {IToken[]} tokenVector
+ */
+function handleElementAttributeRanges(astNode, ctx, tokenVector) {
+ if (exists(ctx.Name)) {
+ const startOffset = ctx.Name[0].endOffset + 2;
+ // Valid `attributesRange` exists
+ if (exists(ctx.START_CLOSE) || exists(ctx.SLASH_CLOSE)) {
+ const endOffset =
+ (exists(ctx.START_CLOSE)
+ ? ctx.START_CLOSE[0].startOffset
+ : ctx.SLASH_CLOSE[0].startOffset) - 1;
+ astNode.syntax.attributesRange = { startOffset, endOffset };
+ }
+ // Have to scan-ahead and guess where the attributes range ends
+ else {
+ const hasAttributes = isArray(ctx.attribute);
+ const lastKnownAttribRangeTokenEnd = hasAttributes
+ ? last(ctx.attribute).location.endOffset
+ : ctx.Name[0].endOffset;
+ const nextTextualToken = findNextTextualToken(
+ tokenVector,
+ lastKnownAttribRangeTokenEnd
+ );
+ if (nextTextualToken !== null) {
+ astNode.syntax.guessedAttributesRange = {
+ startOffset,
+ endOffset: nextTextualToken.endOffset - 1
+ };
+ }
+ }
+ }
+}
+
module.exports = {
buildAst: buildAst
};
diff --git a/packages/ast/package.json b/packages/ast/package.json
index 6f4b1a82..7781bacd 100644
--- a/packages/ast/package.json
+++ b/packages/ast/package.json
@@ -11,6 +11,7 @@
"license": "Apache-2.0",
"typings": "./api.d.ts",
"dependencies": {
+ "@xml-tools/common": "^0.0.1",
"@xml-tools/parser": "^0.4.0",
"lodash": "4.17.15"
},
diff --git a/packages/ast/scripts/update-snapshots.js b/packages/ast/scripts/update-snapshots.js
index 3a07d146..61ae7312 100644
--- a/packages/ast/scripts/update-snapshots.js
+++ b/packages/ast/scripts/update-snapshots.js
@@ -21,8 +21,8 @@ xmlSampleFiles.forEach(fileDesc => {
const xmlInput = readFileSync(fileDesc.path, "utf8");
const simpleNewLinesInput = xmlInput.replace(/\r\n/g, "\n");
console.log(`Reading <${fileDesc.path}>`);
- const { cst } = parse(simpleNewLinesInput);
- const ast = buildAst(cst);
+ const { cst, tokenVector } = parse(simpleNewLinesInput);
+ const ast = buildAst(cst, tokenVector);
modifyAstForAssertions(ast);
const snapshotOutput = `module.exports = { ast : ${JSON.stringify(ast)}}`;
const formattedSnapshotOutput = format(snapshotOutput, { parser: "babel" });
diff --git a/packages/ast/test/sample-test.js b/packages/ast/test/sample-test.js
index 7cde94b8..5ad52a0c 100644
--- a/packages/ast/test/sample-test.js
+++ b/packages/ast/test/sample-test.js
@@ -15,12 +15,14 @@ function executeSampleTest(dirPath, assertNoErrors) {
const inputPath = resolve(dirPath, "input.xml");
const inputText = readFileSync(inputPath).toString("utf8");
const simpleNewLinesInput = inputText.replace(/\r\n/g, "\n");
- const { cst, lexErrors, parseErrors } = parse(simpleNewLinesInput);
+ const { cst, tokenVector, lexErrors, parseErrors } = parse(
+ simpleNewLinesInput
+ );
if (assertNoErrors === true) {
expect(lexErrors).to.be.empty;
expect(parseErrors).to.be.empty;
}
- const ast = buildAst(cst);
+ const ast = buildAst(cst, tokenVector);
assertParentPropsAreValid(ast);
modifyAstForAssertions(ast);
const expectedOutput = require(resolve(dirPath, "output.js")).ast;
diff --git a/packages/ast/test/snapshots/invalid/attributes-no-value-last/output.js b/packages/ast/test/snapshots/invalid/attributes-no-value-last/output.js
index 3178ed1e..3cf7a4dc 100644
--- a/packages/ast/test/snapshots/invalid/attributes-no-value-last/output.js
+++ b/packages/ast/test/snapshots/invalid/attributes-no-value-last/output.js
@@ -41,7 +41,8 @@ module.exports = {
openName: { image: "note", startOffset: 1, endOffset: 4 },
closeName: { image: "note", startOffset: 40, endOffset: 43 },
openBody: { startOffset: 0, endOffset: 37 },
- closeBody: { startOffset: 38, endOffset: 44 }
+ closeBody: { startOffset: 38, endOffset: 44 },
+ attributesRange: { startOffset: 6, endOffset: 36 }
}
},
position: { startOffset: 0, endOffset: 45 }
diff --git a/packages/ast/test/snapshots/invalid/attributes-no-value-middle/output.js b/packages/ast/test/snapshots/invalid/attributes-no-value-middle/output.js
index 9df15424..774369b4 100644
--- a/packages/ast/test/snapshots/invalid/attributes-no-value-middle/output.js
+++ b/packages/ast/test/snapshots/invalid/attributes-no-value-middle/output.js
@@ -41,7 +41,8 @@ module.exports = {
openName: { image: "note", startOffset: 1, endOffset: 4 },
closeName: { image: "note", startOffset: 40, endOffset: 43 },
openBody: { startOffset: 0, endOffset: 37 },
- closeBody: { startOffset: 38, endOffset: 44 }
+ closeBody: { startOffset: 38, endOffset: 44 },
+ attributesRange: { startOffset: 6, endOffset: 36 }
}
},
position: { startOffset: 0, endOffset: 45 }
diff --git a/packages/ast/test/snapshots/invalid/attributes-no-value-no-eql-last/output.js b/packages/ast/test/snapshots/invalid/attributes-no-value-no-eql-last/output.js
index b2d8d829..eb3c86e9 100644
--- a/packages/ast/test/snapshots/invalid/attributes-no-value-no-eql-last/output.js
+++ b/packages/ast/test/snapshots/invalid/attributes-no-value-no-eql-last/output.js
@@ -41,7 +41,8 @@ module.exports = {
openName: { image: "note", startOffset: 1, endOffset: 4 },
closeName: { image: "note", startOffset: 39, endOffset: 42 },
openBody: { startOffset: 0, endOffset: 36 },
- closeBody: { startOffset: 37, endOffset: 43 }
+ closeBody: { startOffset: 37, endOffset: 43 },
+ attributesRange: { startOffset: 6, endOffset: 35 }
}
},
position: { startOffset: 0, endOffset: 44 }
diff --git a/packages/ast/test/snapshots/invalid/attributes-no-value-no-eql-middle/output.js b/packages/ast/test/snapshots/invalid/attributes-no-value-no-eql-middle/output.js
index 6844b3c5..8c7d182e 100644
--- a/packages/ast/test/snapshots/invalid/attributes-no-value-no-eql-middle/output.js
+++ b/packages/ast/test/snapshots/invalid/attributes-no-value-no-eql-middle/output.js
@@ -41,7 +41,8 @@ module.exports = {
openName: { image: "note", startOffset: 1, endOffset: 4 },
closeName: { image: "note", startOffset: 39, endOffset: 42 },
openBody: { startOffset: 0, endOffset: 36 },
- closeBody: { startOffset: 37, endOffset: 43 }
+ closeBody: { startOffset: 37, endOffset: 43 },
+ attributesRange: { startOffset: 6, endOffset: 35 }
}
},
position: { startOffset: 0, endOffset: 44 }
diff --git a/packages/ast/test/snapshots/invalid/attributes-no-value-not-closed-nested/output.js b/packages/ast/test/snapshots/invalid/attributes-no-value-not-closed-nested/output.js
index 4afbf31d..dfcec7a1 100644
--- a/packages/ast/test/snapshots/invalid/attributes-no-value-not-closed-nested/output.js
+++ b/packages/ast/test/snapshots/invalid/attributes-no-value-not-closed-nested/output.js
@@ -36,7 +36,8 @@ module.exports = {
textContents: [],
position: { startOffset: 10, endOffset: 35 },
syntax: {
- openName: { image: "nested", startOffset: 11, endOffset: 16 }
+ openName: { image: "nested", startOffset: 11, endOffset: 16 },
+ guessedAttributesRange: { startOffset: 18, endOffset: 40 }
}
},
{
@@ -57,7 +58,8 @@ module.exports = {
openName: { image: "nest2", startOffset: 42, endOffset: 46 },
closeName: { image: "nest2", startOffset: 61, endOffset: 65 },
openBody: { startOffset: 41, endOffset: 47 },
- closeBody: { startOffset: 59, endOffset: 66 }
+ closeBody: { startOffset: 59, endOffset: 66 },
+ attributesRange: { startOffset: 48, endOffset: 46 }
}
},
{
@@ -89,7 +91,8 @@ module.exports = {
openName: { image: "nested3", startOffset: 73, endOffset: 79 },
closeName: { image: "nested3", startOffset: 94, endOffset: 100 },
openBody: { startOffset: 72, endOffset: 90 },
- closeBody: { startOffset: 92, endOffset: 101 }
+ closeBody: { startOffset: 92, endOffset: 101 },
+ attributesRange: { startOffset: 81, endOffset: 89 }
}
}
],
@@ -115,7 +118,8 @@ module.exports = {
openName: { image: "top", startOffset: 1, endOffset: 3 },
closeName: { image: "top", startOffset: 105, endOffset: 107 },
openBody: { startOffset: 0, endOffset: 4 },
- closeBody: { startOffset: 103, endOffset: 108 }
+ closeBody: { startOffset: 103, endOffset: 108 },
+ attributesRange: { startOffset: 5, endOffset: 3 }
}
},
position: { startOffset: 0, endOffset: 109 }
diff --git a/packages/ast/test/snapshots/invalid/bad-namespace/output.js b/packages/ast/test/snapshots/invalid/bad-namespace/output.js
index 7300d09e..aafe9b1a 100644
--- a/packages/ast/test/snapshots/invalid/bad-namespace/output.js
+++ b/packages/ast/test/snapshots/invalid/bad-namespace/output.js
@@ -33,7 +33,8 @@ module.exports = {
openName: { image: "f:name", startOffset: 25, endOffset: 30 },
closeName: { image: "f:name", startOffset: 44, endOffset: 49 },
openBody: { startOffset: 24, endOffset: 31 },
- closeBody: { startOffset: 42, endOffset: 50 }
+ closeBody: { startOffset: 42, endOffset: 50 },
+ attributesRange: { startOffset: 32, endOffset: 30 }
},
ns: "f"
},
@@ -55,7 +56,8 @@ module.exports = {
openName: { image: "f:width", startOffset: 57, endOffset: 63 },
closeName: { image: "f:width", startOffset: 69, endOffset: 75 },
openBody: { startOffset: 56, endOffset: 64 },
- closeBody: { startOffset: 67, endOffset: 76 }
+ closeBody: { startOffset: 67, endOffset: 76 },
+ attributesRange: { startOffset: 65, endOffset: 63 }
},
ns: "f"
},
@@ -77,7 +79,8 @@ module.exports = {
openName: { image: "f:length", startOffset: 83, endOffset: 90 },
closeName: { image: "f:length", startOffset: 96, endOffset: 103 },
openBody: { startOffset: 82, endOffset: 91 },
- closeBody: { startOffset: 94, endOffset: 104 }
+ closeBody: { startOffset: 94, endOffset: 104 },
+ attributesRange: { startOffset: 92, endOffset: 90 }
},
ns: "f"
}
@@ -109,7 +112,8 @@ module.exports = {
openName: { image: "f:table", startOffset: 2, endOffset: 8 },
closeName: { image: "f:table", startOffset: 108, endOffset: 114 },
openBody: { startOffset: 1, endOffset: 18 },
- closeBody: { startOffset: 106, endOffset: 115 }
+ closeBody: { startOffset: 106, endOffset: 115 },
+ attributesRange: { startOffset: 10, endOffset: 17 }
},
ns: "f"
},
diff --git a/packages/ast/test/snapshots/invalid/element-name-empty-last/output.js b/packages/ast/test/snapshots/invalid/element-name-empty-last/output.js
index 7921e401..d797e9a3 100644
--- a/packages/ast/test/snapshots/invalid/element-name-empty-last/output.js
+++ b/packages/ast/test/snapshots/invalid/element-name-empty-last/output.js
@@ -25,7 +25,8 @@ module.exports = {
openName: { image: "to", startOffset: 12, endOffset: 13 },
closeName: { image: "to", startOffset: 21, endOffset: 22 },
openBody: { startOffset: 11, endOffset: 14 },
- closeBody: { startOffset: 19, endOffset: 23 }
+ closeBody: { startOffset: 19, endOffset: 23 },
+ attributesRange: { startOffset: 15, endOffset: 13 }
}
},
{
@@ -46,7 +47,8 @@ module.exports = {
openName: { image: "from", startOffset: 30, endOffset: 33 },
closeName: { image: "from", startOffset: 41, endOffset: 44 },
openBody: { startOffset: 29, endOffset: 34 },
- closeBody: { startOffset: 39, endOffset: 45 }
+ closeBody: { startOffset: 39, endOffset: 45 },
+ attributesRange: { startOffset: 35, endOffset: 33 }
}
},
{
@@ -82,7 +84,8 @@ module.exports = {
openName: { image: "note", startOffset: 1, endOffset: 4 },
closeName: { image: "note", startOffset: 55, endOffset: 58 },
openBody: { startOffset: 0, endOffset: 5 },
- closeBody: { startOffset: 53, endOffset: 59 }
+ closeBody: { startOffset: 53, endOffset: 59 },
+ attributesRange: { startOffset: 6, endOffset: 4 }
}
},
position: { startOffset: 0, endOffset: 60 }
diff --git a/packages/ast/test/snapshots/invalid/element-name-empty-middle-comment/output.js b/packages/ast/test/snapshots/invalid/element-name-empty-middle-comment/output.js
index 86e209b0..6d2cfe85 100644
--- a/packages/ast/test/snapshots/invalid/element-name-empty-middle-comment/output.js
+++ b/packages/ast/test/snapshots/invalid/element-name-empty-middle-comment/output.js
@@ -25,7 +25,8 @@ module.exports = {
openName: { image: "to", startOffset: 12, endOffset: 13 },
closeName: { image: "to", startOffset: 21, endOffset: 22 },
openBody: { startOffset: 11, endOffset: 14 },
- closeBody: { startOffset: 19, endOffset: 23 }
+ closeBody: { startOffset: 19, endOffset: 23 },
+ attributesRange: { startOffset: 15, endOffset: 13 }
}
},
{
@@ -56,7 +57,8 @@ module.exports = {
openName: { image: "from", startOffset: 65, endOffset: 68 },
closeName: { image: "from", startOffset: 76, endOffset: 79 },
openBody: { startOffset: 64, endOffset: 69 },
- closeBody: { startOffset: 74, endOffset: 80 }
+ closeBody: { startOffset: 74, endOffset: 80 },
+ attributesRange: { startOffset: 70, endOffset: 68 }
}
}
],
@@ -82,7 +84,8 @@ module.exports = {
openName: { image: "note", startOffset: 1, endOffset: 4 },
closeName: { image: "note", startOffset: 84, endOffset: 87 },
openBody: { startOffset: 0, endOffset: 5 },
- closeBody: { startOffset: 82, endOffset: 88 }
+ closeBody: { startOffset: 82, endOffset: 88 },
+ attributesRange: { startOffset: 6, endOffset: 4 }
}
},
position: { startOffset: 0, endOffset: 89 }
diff --git a/packages/ast/test/snapshots/invalid/element-name-empty-middle/output.js b/packages/ast/test/snapshots/invalid/element-name-empty-middle/output.js
index ec2bf636..02569f12 100644
--- a/packages/ast/test/snapshots/invalid/element-name-empty-middle/output.js
+++ b/packages/ast/test/snapshots/invalid/element-name-empty-middle/output.js
@@ -25,7 +25,8 @@ module.exports = {
openName: { image: "to", startOffset: 12, endOffset: 13 },
closeName: { image: "to", startOffset: 21, endOffset: 22 },
openBody: { startOffset: 11, endOffset: 14 },
- closeBody: { startOffset: 19, endOffset: 23 }
+ closeBody: { startOffset: 19, endOffset: 23 },
+ attributesRange: { startOffset: 15, endOffset: 13 }
}
},
{
@@ -56,7 +57,8 @@ module.exports = {
openName: { image: "from", startOffset: 36, endOffset: 39 },
closeName: { image: "from", startOffset: 47, endOffset: 50 },
openBody: { startOffset: 35, endOffset: 40 },
- closeBody: { startOffset: 45, endOffset: 51 }
+ closeBody: { startOffset: 45, endOffset: 51 },
+ attributesRange: { startOffset: 41, endOffset: 39 }
}
}
],
@@ -82,7 +84,8 @@ module.exports = {
openName: { image: "note", startOffset: 1, endOffset: 4 },
closeName: { image: "note", startOffset: 55, endOffset: 58 },
openBody: { startOffset: 0, endOffset: 5 },
- closeBody: { startOffset: 53, endOffset: 59 }
+ closeBody: { startOffset: 53, endOffset: 59 },
+ attributesRange: { startOffset: 6, endOffset: 4 }
}
},
position: { startOffset: 0, endOffset: 60 }
diff --git a/packages/ast/test/snapshots/invalid/element-name-last/output.js b/packages/ast/test/snapshots/invalid/element-name-last/output.js
index b6ebd28f..8d199795 100644
--- a/packages/ast/test/snapshots/invalid/element-name-last/output.js
+++ b/packages/ast/test/snapshots/invalid/element-name-last/output.js
@@ -25,7 +25,8 @@ module.exports = {
openName: { image: "to", startOffset: 12, endOffset: 13 },
closeName: { image: "to", startOffset: 21, endOffset: 22 },
openBody: { startOffset: 11, endOffset: 14 },
- closeBody: { startOffset: 19, endOffset: 23 }
+ closeBody: { startOffset: 19, endOffset: 23 },
+ attributesRange: { startOffset: 15, endOffset: 13 }
}
},
{
@@ -46,7 +47,8 @@ module.exports = {
openName: { image: "from", startOffset: 30, endOffset: 33 },
closeName: { image: "from", startOffset: 41, endOffset: 44 },
openBody: { startOffset: 29, endOffset: 34 },
- closeBody: { startOffset: 39, endOffset: 45 }
+ closeBody: { startOffset: 39, endOffset: 45 },
+ attributesRange: { startOffset: 35, endOffset: 33 }
}
},
{
@@ -57,7 +59,10 @@ module.exports = {
subElements: [],
textContents: [],
position: { startOffset: 51, endOffset: 53 },
- syntax: { openName: { image: "ad", startOffset: 52, endOffset: 53 } }
+ syntax: {
+ openName: { image: "ad", startOffset: 52, endOffset: 53 },
+ guessedAttributesRange: { startOffset: 55, endOffset: 55 }
+ }
}
],
textContents: [
@@ -82,7 +87,8 @@ module.exports = {
openName: { image: "note", startOffset: 1, endOffset: 4 },
closeName: { image: "note", startOffset: 57, endOffset: 60 },
openBody: { startOffset: 0, endOffset: 5 },
- closeBody: { startOffset: 55, endOffset: 61 }
+ closeBody: { startOffset: 55, endOffset: 61 },
+ attributesRange: { startOffset: 6, endOffset: 4 }
}
},
position: { startOffset: 0, endOffset: 62 }
diff --git a/packages/ast/test/snapshots/invalid/element-name-middle/output.js b/packages/ast/test/snapshots/invalid/element-name-middle/output.js
index b5a02406..9cec29d5 100644
--- a/packages/ast/test/snapshots/invalid/element-name-middle/output.js
+++ b/packages/ast/test/snapshots/invalid/element-name-middle/output.js
@@ -25,7 +25,8 @@ module.exports = {
openName: { image: "to", startOffset: 12, endOffset: 13 },
closeName: { image: "to", startOffset: 21, endOffset: 22 },
openBody: { startOffset: 11, endOffset: 14 },
- closeBody: { startOffset: 19, endOffset: 23 }
+ closeBody: { startOffset: 19, endOffset: 23 },
+ attributesRange: { startOffset: 15, endOffset: 13 }
}
},
{
@@ -36,7 +37,10 @@ module.exports = {
subElements: [],
textContents: [],
position: { startOffset: 29, endOffset: 31 },
- syntax: { openName: { image: "ad", startOffset: 30, endOffset: 31 } }
+ syntax: {
+ openName: { image: "ad", startOffset: 30, endOffset: 31 },
+ guessedAttributesRange: { startOffset: 33, endOffset: 36 }
+ }
},
{
type: "XMLElement",
@@ -56,7 +60,8 @@ module.exports = {
openName: { image: "from", startOffset: 38, endOffset: 41 },
closeName: { image: "from", startOffset: 49, endOffset: 52 },
openBody: { startOffset: 37, endOffset: 42 },
- closeBody: { startOffset: 47, endOffset: 53 }
+ closeBody: { startOffset: 47, endOffset: 53 },
+ attributesRange: { startOffset: 43, endOffset: 41 }
}
},
{
@@ -77,7 +82,8 @@ module.exports = {
openName: { image: "city", startOffset: 60, endOffset: 63 },
closeName: { image: "city", startOffset: 69, endOffset: 72 },
openBody: { startOffset: 59, endOffset: 64 },
- closeBody: { startOffset: 67, endOffset: 73 }
+ closeBody: { startOffset: 67, endOffset: 73 },
+ attributesRange: { startOffset: 65, endOffset: 63 }
}
}
],
@@ -108,7 +114,8 @@ module.exports = {
openName: { image: "note", startOffset: 1, endOffset: 4 },
closeName: { image: "note", startOffset: 77, endOffset: 80 },
openBody: { startOffset: 0, endOffset: 5 },
- closeBody: { startOffset: 75, endOffset: 81 }
+ closeBody: { startOffset: 75, endOffset: 81 },
+ attributesRange: { startOffset: 6, endOffset: 4 }
}
},
position: { startOffset: 0, endOffset: 82 }
diff --git a/packages/ast/test/snapshots/valid/attributes/output.js b/packages/ast/test/snapshots/valid/attributes/output.js
index 57b0759d..3c6b9125 100644
--- a/packages/ast/test/snapshots/valid/attributes/output.js
+++ b/packages/ast/test/snapshots/valid/attributes/output.js
@@ -34,7 +34,8 @@ module.exports = {
openName: { image: "note", startOffset: 1, endOffset: 4 },
closeName: { image: "note", startOffset: 32, endOffset: 35 },
openBody: { startOffset: 0, endOffset: 29 },
- closeBody: { startOffset: 30, endOffset: 36 }
+ closeBody: { startOffset: 30, endOffset: 36 },
+ attributesRange: { startOffset: 6, endOffset: 28 }
}
},
position: { startOffset: 0, endOffset: 37 }
diff --git a/packages/ast/test/snapshots/valid/complex-contents/output.js b/packages/ast/test/snapshots/valid/complex-contents/output.js
index 9b91862a..3838d136 100644
--- a/packages/ast/test/snapshots/valid/complex-contents/output.js
+++ b/packages/ast/test/snapshots/valid/complex-contents/output.js
@@ -13,7 +13,8 @@ module.exports = {
openName: { image: "note", startOffset: 10, endOffset: 13 },
closeName: { image: "note", startOffset: 17, endOffset: 20 },
openBody: { startOffset: 9, endOffset: 14 },
- closeBody: { startOffset: 15, endOffset: 21 }
+ closeBody: { startOffset: 15, endOffset: 21 },
+ attributesRange: { startOffset: 15, endOffset: 13 }
}
},
position: { startOffset: 0, endOffset: 22 },
diff --git a/packages/ast/test/snapshots/valid/elements-short-form/output.js b/packages/ast/test/snapshots/valid/elements-short-form/output.js
index daa448a7..a81504de 100644
--- a/packages/ast/test/snapshots/valid/elements-short-form/output.js
+++ b/packages/ast/test/snapshots/valid/elements-short-form/output.js
@@ -25,7 +25,8 @@ module.exports = {
openName: { image: "to", startOffset: 12, endOffset: 13 },
closeName: { image: "to", startOffset: 21, endOffset: 22 },
openBody: { startOffset: 11, endOffset: 14 },
- closeBody: { startOffset: 19, endOffset: 23 }
+ closeBody: { startOffset: 19, endOffset: 23 },
+ attributesRange: { startOffset: 15, endOffset: 13 }
}
},
{
@@ -49,7 +50,8 @@ module.exports = {
position: { startOffset: 29, endOffset: 46 },
syntax: {
openName: { image: "from", startOffset: 30, endOffset: 33 },
- openBody: { startOffset: 29, endOffset: 46 }
+ openBody: { startOffset: 29, endOffset: 46 },
+ attributesRange: { startOffset: 35, endOffset: 44 }
}
}
],
@@ -75,7 +77,8 @@ module.exports = {
openName: { image: "note", startOffset: 1, endOffset: 4 },
closeName: { image: "note", startOffset: 50, endOffset: 53 },
openBody: { startOffset: 0, endOffset: 5 },
- closeBody: { startOffset: 48, endOffset: 54 }
+ closeBody: { startOffset: 48, endOffset: 54 },
+ attributesRange: { startOffset: 6, endOffset: 4 }
}
},
position: { startOffset: 0, endOffset: 55 }
diff --git a/packages/ast/test/snapshots/valid/elements/output.js b/packages/ast/test/snapshots/valid/elements/output.js
index 15d719a8..9d72e2b0 100644
--- a/packages/ast/test/snapshots/valid/elements/output.js
+++ b/packages/ast/test/snapshots/valid/elements/output.js
@@ -25,7 +25,8 @@ module.exports = {
openName: { image: "to", startOffset: 12, endOffset: 13 },
closeName: { image: "to", startOffset: 21, endOffset: 22 },
openBody: { startOffset: 11, endOffset: 14 },
- closeBody: { startOffset: 19, endOffset: 23 }
+ closeBody: { startOffset: 19, endOffset: 23 },
+ attributesRange: { startOffset: 15, endOffset: 13 }
}
},
{
@@ -46,7 +47,8 @@ module.exports = {
openName: { image: "from", startOffset: 30, endOffset: 33 },
closeName: { image: "from", startOffset: 40, endOffset: 43 },
openBody: { startOffset: 29, endOffset: 34 },
- closeBody: { startOffset: 38, endOffset: 44 }
+ closeBody: { startOffset: 38, endOffset: 44 },
+ attributesRange: { startOffset: 35, endOffset: 33 }
}
}
],
@@ -72,7 +74,8 @@ module.exports = {
openName: { image: "note", startOffset: 1, endOffset: 4 },
closeName: { image: "note", startOffset: 48, endOffset: 51 },
openBody: { startOffset: 0, endOffset: 5 },
- closeBody: { startOffset: 46, endOffset: 52 }
+ closeBody: { startOffset: 46, endOffset: 52 },
+ attributesRange: { startOffset: 6, endOffset: 4 }
}
},
position: { startOffset: 0, endOffset: 53 }
diff --git a/packages/ast/test/snapshots/valid/namespaces/output.js b/packages/ast/test/snapshots/valid/namespaces/output.js
index 77665e33..e100a41c 100644
--- a/packages/ast/test/snapshots/valid/namespaces/output.js
+++ b/packages/ast/test/snapshots/valid/namespaces/output.js
@@ -60,7 +60,8 @@ module.exports = {
openName: { image: "f:name", startOffset: 86, endOffset: 91 },
closeName: { image: "f:name", startOffset: 105, endOffset: 110 },
openBody: { startOffset: 85, endOffset: 92 },
- closeBody: { startOffset: 103, endOffset: 111 }
+ closeBody: { startOffset: 103, endOffset: 111 },
+ attributesRange: { startOffset: 93, endOffset: 91 }
},
ns: "f"
},
@@ -85,7 +86,8 @@ module.exports = {
openName: { image: "f:width", startOffset: 118, endOffset: 124 },
closeName: { image: "f:width", startOffset: 130, endOffset: 136 },
openBody: { startOffset: 117, endOffset: 125 },
- closeBody: { startOffset: 128, endOffset: 137 }
+ closeBody: { startOffset: 128, endOffset: 137 },
+ attributesRange: { startOffset: 126, endOffset: 124 }
},
ns: "f"
},
@@ -110,7 +112,8 @@ module.exports = {
openName: { image: "f:length", startOffset: 144, endOffset: 151 },
closeName: { image: "f:length", startOffset: 157, endOffset: 164 },
openBody: { startOffset: 143, endOffset: 152 },
- closeBody: { startOffset: 155, endOffset: 165 }
+ closeBody: { startOffset: 155, endOffset: 165 },
+ attributesRange: { startOffset: 153, endOffset: 151 }
},
ns: "f"
},
@@ -143,7 +146,8 @@ module.exports = {
endOffset: 208
},
openBody: { startOffset: 171, endOffset: 183 },
- closeBody: { startOffset: 196, endOffset: 209 }
+ closeBody: { startOffset: 196, endOffset: 209 },
+ attributesRange: { startOffset: 184, endOffset: 182 }
}
}
],
@@ -179,7 +183,8 @@ module.exports = {
openName: { image: "f:table", startOffset: 2, endOffset: 8 },
closeName: { image: "f:table", startOffset: 213, endOffset: 219 },
openBody: { startOffset: 1, endOffset: 79 },
- closeBody: { startOffset: 211, endOffset: 220 }
+ closeBody: { startOffset: 211, endOffset: 220 },
+ attributesRange: { startOffset: 10, endOffset: 78 }
},
ns: "f"
},
diff --git a/packages/ast/test/snapshots/valid/prolog-no-attriibs/output.js b/packages/ast/test/snapshots/valid/prolog-no-attriibs/output.js
index 35300141..4e86477c 100644
--- a/packages/ast/test/snapshots/valid/prolog-no-attriibs/output.js
+++ b/packages/ast/test/snapshots/valid/prolog-no-attriibs/output.js
@@ -25,7 +25,8 @@ module.exports = {
openName: { image: "to", startOffset: 36, endOffset: 37 },
closeName: { image: "to", startOffset: 45, endOffset: 46 },
openBody: { startOffset: 35, endOffset: 38 },
- closeBody: { startOffset: 43, endOffset: 47 }
+ closeBody: { startOffset: 43, endOffset: 47 },
+ attributesRange: { startOffset: 39, endOffset: 37 }
}
},
{
@@ -46,7 +47,8 @@ module.exports = {
openName: { image: "from", startOffset: 64, endOffset: 67 },
closeName: { image: "from", startOffset: 74, endOffset: 77 },
openBody: { startOffset: 63, endOffset: 68 },
- closeBody: { startOffset: 72, endOffset: 78 }
+ closeBody: { startOffset: 72, endOffset: 78 },
+ attributesRange: { startOffset: 69, endOffset: 67 }
}
}
],
@@ -87,7 +89,8 @@ module.exports = {
openName: { image: "note", startOffset: 1, endOffset: 4 },
closeName: { image: "note", startOffset: 92, endOffset: 95 },
openBody: { startOffset: 0, endOffset: 5 },
- closeBody: { startOffset: 90, endOffset: 96 }
+ closeBody: { startOffset: 90, endOffset: 96 },
+ attributesRange: { startOffset: 6, endOffset: 4 }
}
},
position: { startOffset: 0, endOffset: 97 }
diff --git a/packages/ast/test/snapshots/valid/prolog/output.js b/packages/ast/test/snapshots/valid/prolog/output.js
index 002261c5..92e01832 100644
--- a/packages/ast/test/snapshots/valid/prolog/output.js
+++ b/packages/ast/test/snapshots/valid/prolog/output.js
@@ -13,7 +13,8 @@ module.exports = {
openName: { image: "note", startOffset: 40, endOffset: 43 },
closeName: { image: "note", startOffset: 47, endOffset: 50 },
openBody: { startOffset: 39, endOffset: 44 },
- closeBody: { startOffset: 45, endOffset: 51 }
+ closeBody: { startOffset: 45, endOffset: 51 },
+ attributesRange: { startOffset: 45, endOffset: 43 }
}
},
position: { startOffset: 0, endOffset: 52 },
diff --git a/packages/ast/test/visitor/visitor-spec.js b/packages/ast/test/visitor/visitor-spec.js
index c6401d62..c54d7947 100644
--- a/packages/ast/test/visitor/visitor-spec.js
+++ b/packages/ast/test/visitor/visitor-spec.js
@@ -110,7 +110,7 @@ describe("The XML AST Visitor", () => {
});
function getAst(text) {
- const { cst } = parse(text);
- const ast = buildAst(cst);
+ const { cst, tokenVector } = parse(text);
+ const ast = buildAst(cst, tokenVector);
return ast;
}
diff --git a/packages/content-assist/lib/api.js b/packages/content-assist/lib/api.js
index 8b7ad745..37fe48e8 100644
--- a/packages/content-assist/lib/api.js
+++ b/packages/content-assist/lib/api.js
@@ -1,5 +1,5 @@
const { parse } = require("@xml-tools/parser");
-const { buildAst } = require("@xml-tools/ast");
+const { buildAst, tokenVector } = require("@xml-tools/ast");
const { defaultsDeep, flatMap } = require("lodash");
const { computeCompletionContext } = require("./content-assist");
@@ -14,7 +14,7 @@ function getSuggestions(options) {
}
});
const { cst, tokenVector } = parse(actualOptions.text);
- const ast = buildAst(cst);
+ const ast = buildAst(cst, tokenVector);
const { providerType, providerArgs } = computeCompletionContext({
cst: cst,
diff --git a/packages/simple-schema/README.md b/packages/simple-schema/README.md
index 521beae2..cfebc468 100644
--- a/packages/simple-schema/README.md
+++ b/packages/simple-schema/README.md
@@ -71,8 +71,8 @@ Please see the [TypeScript Definitions](./api.d.ts) for full API details.
const { validate } = require("@xml-tools/validation");
const { getSchemaValidators } = require("@xml-tools/simple-schema");
- const { cst } = parse(xmlText);
- const xmlDoc = buildAst(cst);
+ const { cst, tokenVector } = parse(xmlText);
+ const xmlDoc = buildAst(cst, tokenVector);
const schemaValidators = getSchemaValidators(schema);
const issues = validate({
doc: xmlDoc,
diff --git a/packages/simple-schema/package.json b/packages/simple-schema/package.json
index 1747e2fb..aebcade2 100644
--- a/packages/simple-schema/package.json
+++ b/packages/simple-schema/package.json
@@ -11,7 +11,7 @@
"license": "Apache-2.0",
"typings": "./api.d.ts",
"dependencies": {
- "@xml-tools/ast": "^0.3.0",
+ "@xml-tools/ast": "^0.5.0",
"@xml-tools/content-assist": "^0.4.2",
"lodash": "4.17.15"
},
diff --git a/packages/simple-schema/test/validators/utils.js b/packages/simple-schema/test/validators/utils.js
index 449563a7..694dc0aa 100644
--- a/packages/simple-schema/test/validators/utils.js
+++ b/packages/simple-schema/test/validators/utils.js
@@ -10,8 +10,8 @@ const { getSchemaValidators } = require("../../");
* @returns {ValidationIssue[] | *}
*/
function validateBySchema(xmlText, schema) {
- const { cst } = parse(xmlText);
- const xmlDoc = buildAst(cst);
+ const { cst, tokenVector } = parse(xmlText);
+ const xmlDoc = buildAst(cst, tokenVector);
const schemaValidators = getSchemaValidators(schema);
const issues = validate({
doc: xmlDoc,
diff --git a/packages/validation/README.md b/packages/validation/README.md
index 61ba0e0b..bde9195c 100644
--- a/packages/validation/README.md
+++ b/packages/validation/README.md
@@ -30,8 +30,8 @@ const xmlText = `
`;
-const { cst } = parse(xmlText);
-const xmlDocAst = buildAst(cst);
+const { cst, tokenVector } = parse(xmlText);
+const xmlDocAst = buildAst(cst, tokenVector);
const issues = validate({
doc: xmlDocAst,
validators: {
diff --git a/packages/validation/test/validate-apis-spec.js b/packages/validation/test/validate-apis-spec.js
index cf5c4937..8463dbbb 100644
--- a/packages/validation/test/validate-apis-spec.js
+++ b/packages/validation/test/validate-apis-spec.js
@@ -56,7 +56,7 @@ describe("The XML Validations APIs", () => {
});
function xmlTextToAst(text) {
- const { cst } = parse(text);
- const ast = buildAst(cst);
+ const { cst, tokenVector } = parse(text);
+ const ast = buildAst(cst, tokenVector);
return ast;
}
diff --git a/yarn.lock b/yarn.lock
index c34e8a21..d30fa867 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1108,21 +1108,6 @@
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.2.0.tgz#d688d574400d96c5b0114968705366f431831e1a"
integrity sha512-1OzrNb4RuAzIT7wHSsgZRlMBlNsJl+do6UblR7JMW4oB7bbR+uBEYtUh7gEc/jM84GGilh68lSOokyM/zNUlBA==
-"@xml-tools/ast@^0.3.0":
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/@xml-tools/ast/-/ast-0.3.0.tgz#aa67175443eece11fb0c00507f07570cb2ac3078"
- integrity sha512-qpOQg2mhEgOp8BNVVZgAoTQwAHgZJgneCFN7yB6NSMqXUvdpLYJQzqRo1+qe8ATqEAFqLh3eG98oFJW2isinaA==
- dependencies:
- "@xml-tools/parser" "^0.3.0"
- lodash "4.17.15"
-
-"@xml-tools/parser@^0.3.0":
- version "0.3.4"
- resolved "https://registry.yarnpkg.com/@xml-tools/parser/-/parser-0.3.4.tgz#709087bedca42ad11942a2632979e13b548dbfad"
- integrity sha512-cw20poVHMQNN6KldoTdjybUE8uoXmlmA9OYfukcIZhhV+B2nHMoEGP9u+UDYelsmUnng80YwlRQiGHd7/5aXew==
- dependencies:
- chevrotain "6.5.0"
-
"@zkochan/cmd-shim@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz#2ab8ed81f5bb5452a85f25758eb9b8681982fd2e"