Skip to content

Commit fbdf64e

Browse files
committed
check arity of types: 'array', 'element', 'map', 'attribute'
1 parent eb899e9 commit fbdf64e

File tree

3 files changed

+30
-14
lines changed

3 files changed

+30
-14
lines changed

src/xsltTokenDiagnostics.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ export class XsltTokenDiagnostics {
118118
public static readonly xslInclude = 'xsl:include';
119119
public static readonly xslImport = 'xsl:import';
120120
public static readonly xmlChars = ['lt', 'gt', 'quot', 'apos', 'amp'];
121+
public static readonly typesWithMaxArity2 = ['map', 'attribute', 'element'];
122+
public static readonly typesWithMinArity0 = ['element', 'attribute'];
123+
public static readonly typesWithArity1 = ['array'];
121124

122125

123126
public static readonly xslFunction = 'xsl:function';
@@ -1182,13 +1185,19 @@ export class XsltTokenDiagnostics {
11821185
if (token.charType === CharLevelState.rB && xpathStack.length > 0) {
11831186
// check arity is true for type: map(xs:integer, xs:integer)
11841187
const lastStackEntry = xpathStack[xpathStack.length - 1];
1185-
if (lastStackEntry.function && lastStackEntry.functionArity !== undefined && lastStackEntry.function.tokenType === TokenLevelState.simpleType) {
1186-
const isMap = lastStackEntry.function.value === 'map';
1188+
if (lastStackEntry.function && lastStackEntry.functionArity !== undefined && lastStackEntry.function.tokenType !== TokenLevelState.function) {
1189+
const typeName = lastStackEntry.function.value;
1190+
const maxArityNumber = this.typesWithMaxArity2.includes(typeName) ? 2 : 1;
1191+
const minArityNumber = this.typesWithArity1.includes(typeName) ? 1 : 0;
11871192
const actualArity = (prevToken?.charType !== CharLevelState.lB)? lastStackEntry.functionArity + 1 : 0;
1188-
if (((isMap && actualArity > 2) || (!isMap && actualArity > 1)) || actualArity === 0 ) {
1193+
if ((actualArity > maxArityNumber) || actualArity < minArityNumber ) {
1194+
const arityText =
1195+
minArityNumber === 0 && maxArityNumber === 1 ? '0 or 1' :
1196+
minArityNumber === 1 && maxArityNumber === 1 ? '1' :
1197+
minArityNumber === 1 && maxArityNumber === 2 ? '1 or 2' : '0 or 1 (or 2 if schema-aware)';
11891198
const errToken = lastStackEntry.function;
11901199
errToken.error = ErrorType.XPathTypeFullArity;
1191-
errToken.value = errToken.value + '#' + actualArity;
1200+
errToken.value = errToken.value + '#' + actualArity + '#' + arityText;
11921201
problemTokens.push(errToken);
11931202
}
11941203
}
@@ -1718,7 +1727,7 @@ export class XsltTokenDiagnostics {
17181727
if (!anonymousFunctionParams && prevToken?.tokenType !== TokenLevelState.nodeType) {
17191728
anonymousFunctionParams = prevToken?.tokenType === TokenLevelState.anonymousFunction;
17201729
}
1721-
if (prevToken?.tokenType === TokenLevelState.function || (withinTypeDeclarationAttr && prevToken?.tokenType && (prevToken.value === 'map' || prevToken.value === 'array'))) {
1730+
if (prevToken?.tokenType === TokenLevelState.function || (withinTypeDeclarationAttr && prevToken && (this.typesWithMaxArity2.includes(prevToken.value) || this.typesWithArity1.includes(prevToken.value)))) {
17221731
functionToken = prevToken;
17231732
} else if (prevToken?.tokenType === TokenLevelState.variable) {
17241733
// TODO: check arity of variables of type 'function'
@@ -3133,9 +3142,11 @@ export class XsltTokenDiagnostics {
31333142
msg = `XPath: Function: '${parts[0]}' with ${parts[1]} arguments not found`;
31343143
break;
31353144
case ErrorType.XPathTypeFullArity:
3136-
const arityMsg = tokenValue === 'map'? '1 or 2' : '1';
31373145
let parts2 = tokenValue.split('#');
3138-
msg = `XPath Type: Expected number of itemType arguments for '${parts2[0]}()' is ${arityMsg} but found: ${parts2[1]}`;
3146+
const arityMsg = parts2[2];
3147+
const arityNum = parts2[1];
3148+
const typeName = parts2[0];
3149+
msg = `XPath Type: Expected number of itemType arguments for '${typeName}()' is ${arityMsg} but found: ${arityNum}`;
31393150
break;
31403151
case ErrorType.XPathFunctionParseHtml:
31413152
errCode = DiagnosticCode.parseHtmlRef;

test/issue-144.xsl

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@
1717
<xsl:variable name="test8" as="xs:anyAtomicType" select="1"/>
1818
<xsl:variable name="test9" as="xs:numeric" select="1"/>
1919
<xsl:variable name="test10" as="array(*)?" select="[]"/>
20-
<xsl:variable name="test11" as="array(map(xs:string, xs:integer))?" select="()"/>
21-
<xsl:variable name="test12" as="element(ct:book)" select="/*"/>
22-
<xsl:variable name="test13" as="attribute(book)" select="/*"/>
23-
<xsl:variable name="test14" as="attribute()" select="/*"/>
24-
<xsl:variable name="test15" as="attribute(*, xs:date)" select="/*"/>
20+
<xsl:variable name="test11" as="map(*)" select="[]"/>
21+
<xsl:variable name="test12" as="array(map(xs:string, xs:integer))?" select="()"/>
22+
<xsl:variable name="test13" as="element(ct:book)" select="/*"/>
23+
<xsl:variable name="test14" as="attribute(book)" select="/*"/>
24+
<xsl:variable name="test15" as="attribute()" select="/*"/>
25+
<xsl:variable name="test16" as="attribute(*, xs:date)" select="//@*"/>
26+
<xsl:variable name="test17" as="element(*, xs:integer)" select="//*"/>
2527

2628

2729
<xsl:function name="fn:main" as="item()*">
@@ -50,7 +52,9 @@
5052
<xsl:variable name="test17-error" as="map( )" select="map{}"/>
5153
<xsl:variable name="test18-error" as="map(xs:integer, xs:integer, xs:integer)" select="map{}"/>
5254
<xsl:variable name="test19-error" as="array(xs:integer, xs:integer)" select="array{}"/>
53-
<xsl:variable name="test20-error" as="attribute(*, xs:date, xs:integer)" select="/*"/>
55+
<xsl:variable name="test20-error" as="attribute(*, xs:date, xs:integer)" select="/@*"/>
56+
<xsl:variable name="test21-error" as="element(*, xs:date, xs:integer)" select="/@*"/>
57+
<xsl:variable name="test22-error" as="array()" select="/*"/>
5458

5559

5660
<?END type declarations WITH ERRORS?>

test/test.xsl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
expand-text="yes"
1010
version="3.0">
1111

12-
<xsl:variable name="test2" as="map(xs:integer, map(xs:string, array(xs:integer*)))?" select="/*"/>
12+
<xsl:variable name="test20-error" as="attribute(*, xs:date, xs:integer)" select="/*"/>
13+
1314

1415
<!-- <xsl:variable name="test" as="map()" select="count(22)"/>
1516
<xsl:variable name="test" as="map( )" select="count(22)"/>

0 commit comments

Comments
 (0)