@@ -118,6 +118,9 @@ export class XsltTokenDiagnostics {
118118public static readonly xslInclude = 'xsl:include' ;
119119public static readonly xslImport = 'xsl:import' ;
120120public 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
123126public static readonly xslFunction = 'xsl:function' ;
@@ -1182,13 +1185,19 @@ export class XsltTokenDiagnostics {
11821185if ( token . charType === CharLevelState . rB && xpathStack . length > 0 ) {
11831186// check arity is true for type: map(xs:integer, xs:integer)
11841187const 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 ;
11871192const 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)' ;
11891198const errToken = lastStackEntry . function ;
11901199errToken . error = ErrorType . XPathTypeFullArity ;
1191- errToken . value = errToken . value + '#' + actualArity ;
1200+ errToken . value = errToken . value + '#' + actualArity + '#' + arityText ;
11921201problemTokens . push ( errToken ) ;
11931202}
11941203}
@@ -1718,7 +1727,7 @@ export class XsltTokenDiagnostics {
17181727if ( ! anonymousFunctionParams && prevToken ?. tokenType !== TokenLevelState . nodeType ) {
17191728anonymousFunctionParams = 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 ) ) ) ) {
17221731functionToken = prevToken ;
17231732} else if ( prevToken ?. tokenType === TokenLevelState . variable ) {
17241733// TODO: check arity of variables of type 'function'
@@ -3133,9 +3142,11 @@ export class XsltTokenDiagnostics {
31333142msg = `XPath: Function: '${ parts [ 0 ] } ' with ${ parts [ 1 ] } arguments not found` ;
31343143break ;
31353144case ErrorType . XPathTypeFullArity :
3136- const arityMsg = tokenValue === 'map' ? '1 or 2' : '1' ;
31373145let 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 } ` ;
31393150break ;
31403151case ErrorType . XPathFunctionParseHtml :
31413152errCode = DiagnosticCode . parseHtmlRef ;
0 commit comments