• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FontoXML / fontoxpath / 4163383878

pending completion
4163383878

Pull #577

github

GitHub
Merge 4c14ab258 into 41890b6e5
Pull Request #577: Dramatically improve parse errors

4896 of 5693 branches covered (86.0%)

Branch coverage included in aggregate %.

34 of 35 new or added lines in 8 files covered. (97.14%)

7 existing lines in 3 files now uncovered.

10529 of 11168 relevant lines covered (94.28%)

97388.98 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.81
/src/parsing/staticallyCompileXPath.ts
1
import { EvaluableExpression } from '../evaluateXPath';
2
import ExecutionSpecificStaticContext from '../expressions/ExecutionSpecificStaticContext';
9✔
3
import Expression from '../expressions/Expression';
4
import StaticContext from '../expressions/StaticContext';
9✔
5
import annotateAst from '../typeInference/annotateAST';
9✔
6
import { AnnotationContext } from '../typeInference/AnnotationContext';
9✔
7
import { FunctionNameResolver } from '../types/Options';
8
import astHelper, { IAST } from './astHelper';
9✔
9
import compileAstToExpression from './compileAstToExpression';
9✔
10
import {
9✔
11
        getStaticCompilationResultFromCache,
12
        storeStaticCompilationResultInCache,
13
} from './compiledExpressionCache';
14
import convertXmlToAst from './convertXmlToAst';
9✔
15
import { enhanceStaticContextWithModule, performStaticCompilationOnModules } from './globalModuleCache';
9✔
16
import normalizeEndOfLines from './normalizeEndOfLines';
9✔
17
import parseExpression from './parseExpression';
9✔
18
import processProlog from './processProlog';
9✔
19

20
enum CACHE_STATE {
9✔
21
        PARSED,
9✔
22
        COMPILED,
9✔
23
        STATIC_ANALYZED,
9✔
24
}
25

26
function createExpressionFromSource(
27
        xpathSource: EvaluableExpression,
28
        compilationOptions: {
29
                allowUpdating: boolean | undefined;
30
                allowXQuery: boolean | undefined;
31
                debug: boolean | undefined;
32
                disableCache: boolean | undefined;
33
        },
34
        namespaceResolver: (namespace: string) => string | null,
35
        variables: { [varName: string]: any },
36
        moduleImports: { [namespaceURI: string]: string },
37
        defaultFunctionNamespaceURI: string,
38
        functionNameResolver: FunctionNameResolver
39
):
40
        | { ast: IAST; state: CACHE_STATE.PARSED }
41
        | { expression: Expression; state: CACHE_STATE.COMPILED | CACHE_STATE.STATIC_ANALYZED } {
42
        const language = compilationOptions.allowXQuery ? 'XQuery' : 'XPath';
29,718✔
43

44
        const fromCache = compilationOptions.disableCache
29,718✔
45
                ? null
46
                : getStaticCompilationResultFromCache(
47
                                xpathSource,
48
                                language,
49
                                namespaceResolver,
50
                                variables,
51
                                moduleImports,
52
                                compilationOptions.debug,
53
                                defaultFunctionNamespaceURI,
54
                                functionNameResolver
55
                  );
56

57
        if (fromCache !== null) {
29,718✔
58
                return {
18,051✔
59
                        state: fromCache.requiresStaticCompilation
18,051!
60
                                ? CACHE_STATE.COMPILED
61
                                : CACHE_STATE.STATIC_ANALYZED,
62
                        expression: fromCache.expression,
63
                };
64
        } else {
65
                // We can not use anything from the cache, parse + compile
66
                const ast =
67
                        typeof xpathSource === 'string'
11,667✔
68
                                ? parseExpression(xpathSource, compilationOptions)
69
                                : convertXmlToAst(xpathSource);
70

71
                return {
11,007✔
72
                        state: CACHE_STATE.PARSED,
73
                        ast,
74
                };
75
        }
76
}
77

78
function buildExpressionFromAst(
79
        ast: IAST,
80
        compilationOptions: {
81
                allowUpdating: boolean | undefined;
82
                allowXQuery: boolean | undefined;
83
                debug: boolean | undefined;
84
                disableCache: boolean | undefined;
85
        },
86
        rootStaticContext: StaticContext,
87
        source: EvaluableExpression
88
) {
89
        const mainModule = astHelper.getFirstChild(ast, 'mainModule');
11,007✔
90
        if (!mainModule) {
11,007!
91
                // This must be a library module
UNCOV
92
                throw new Error('Can not execute a library module.');
×
93
        }
94

95
        const prolog = astHelper.getFirstChild(mainModule, 'prolog');
11,007✔
96

97
        if (prolog) {
11,007✔
98
                if (!compilationOptions.allowXQuery) {
4,824!
UNCOV
99
                        throw new Error(
×
100
                                'XPST0003: Use of XQuery functionality is not allowed in XPath context'
101
                        );
102
                }
103

104
                // XPath with a prolog: we're going to need to statically analyze modules if that didn't
105
                // happen yet:
106
                performStaticCompilationOnModules();
4,824✔
107

108
                const moduleDeclaration = processProlog(prolog, rootStaticContext, true, source);
4,824✔
109
                // Immediately perform static compilation as well
110
                moduleDeclaration.performStaticAnalysis(moduleDeclaration);
4,782✔
111
        }
112

113
        const context = new AnnotationContext(rootStaticContext);
10,956✔
114
        annotateAst(ast, context);
10,956✔
115

116
        const queryBodyContents = astHelper.followPath(mainModule, ['queryBody', '*']);
10,953✔
117

118
        return compileAstToExpression(queryBodyContents, compilationOptions);
10,953✔
119
}
120

121
export default function staticallyCompileXPath(
9✔
122
        selector: EvaluableExpression,
123
        compilationOptions: {
124
                allowUpdating: boolean | undefined;
125
                allowXQuery: boolean | undefined;
126
                debug: boolean | undefined;
127
                disableCache: boolean | undefined;
128
        },
129
        namespaceResolver: (namespace: string) => string | null,
130
        variables: { [varName: string]: any },
131
        moduleImports: { [namespaceURI: string]: string },
132
        defaultFunctionNamespaceURI: string,
133
        functionNameResolver: FunctionNameResolver
134
): { expression: Expression; staticContext: StaticContext } {
135
        const executionSpecificStaticContext = new ExecutionSpecificStaticContext(
29,721✔
136
                namespaceResolver,
137
                variables,
138
                defaultFunctionNamespaceURI,
139
                functionNameResolver
140
        );
141
        const rootStaticContext = new StaticContext(executionSpecificStaticContext);
29,721✔
142

143
        if (Object.keys(moduleImports).length > 0) {
29,721✔
144
                // XPath with imports: we're going to need to statically analyze modules if that didn't
145
                // happen yet:
146
                performStaticCompilationOnModules();
18✔
147
        }
148

149
        Object.keys(moduleImports).forEach((modulePrefix) => {
29,718✔
150
                const moduleURI = moduleImports[modulePrefix];
18✔
151
                enhanceStaticContextWithModule(rootStaticContext, moduleURI);
18✔
152

153
                rootStaticContext.registerNamespace(modulePrefix, moduleURI);
18✔
154
        });
155

156
        if (typeof selector === 'string') {
29,718✔
157
                selector = normalizeEndOfLines(selector);
25,986✔
158
        }
159
        const result = createExpressionFromSource(
29,718✔
160
                selector,
161
                compilationOptions,
162
                namespaceResolver,
163
                variables,
164
                moduleImports,
165
                defaultFunctionNamespaceURI,
166
                functionNameResolver
167
        );
168
        switch (result.state) {
29,058!
169
                case CACHE_STATE.STATIC_ANALYZED:
170
                        return {
18,051✔
171
                                staticContext: rootStaticContext,
172
                                expression: result.expression,
173
                        };
174

175
                case CACHE_STATE.COMPILED: {
UNCOV
176
                        result.expression.performStaticEvaluation(rootStaticContext);
×
177

UNCOV
178
                        const language = compilationOptions.allowXQuery ? 'XQuery' : 'XPath';
×
179
                        storeStaticCompilationResultInCache(
×
180
                                selector,
181
                                language,
182
                                executionSpecificStaticContext,
183
                                moduleImports,
184
                                result.expression,
185
                                compilationOptions.debug,
186
                                defaultFunctionNamespaceURI
187
                        );
188

UNCOV
189
                        return {
×
190
                                staticContext: rootStaticContext,
191
                                expression: result.expression,
192
                        };
193
                }
194
                case CACHE_STATE.PARSED: {
195
                        const expressionFromAst = buildExpressionFromAst(
11,007✔
196
                                result.ast,
197
                                compilationOptions,
198
                                rootStaticContext,
199
                                selector
200
                        );
201
                        expressionFromAst.performStaticEvaluation(rootStaticContext);
10,953✔
202

203
                        if (!compilationOptions.disableCache) {
10,635✔
204
                                const language = compilationOptions.allowXQuery ? 'XQuery' : 'XPath';
10,632✔
205
                                storeStaticCompilationResultInCache(
10,632✔
206
                                        selector,
207
                                        language,
208
                                        executionSpecificStaticContext,
209
                                        moduleImports,
210
                                        expressionFromAst,
211
                                        compilationOptions.debug,
212
                                        defaultFunctionNamespaceURI
213
                                );
214
                        }
215

216
                        return {
10,635✔
217
                                staticContext: rootStaticContext,
218
                                expression: expressionFromAst,
219
                        };
220
                }
221
        }
222
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc