1 | import { DocExcerpt } from '../../nodes';
|
2 | import { TokenSequence } from '../TokenSequence';
|
3 | import { TokenKind } from '../Token';
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | var TokenCoverageChecker = (function () {
|
17 | function TokenCoverageChecker(parserContext) {
|
18 | this._parserContext = parserContext;
|
19 | this._tokenAssociations = [];
|
20 | this._tokenAssociations.length = parserContext.tokens.length;
|
21 | }
|
22 | TokenCoverageChecker.prototype.getGaps = function (rootNode) {
|
23 | this._addNodeTree(rootNode);
|
24 | return this._checkForGaps(false);
|
25 | };
|
26 | TokenCoverageChecker.prototype.reportGaps = function (rootNode) {
|
27 | this._addNodeTree(rootNode);
|
28 | this._checkForGaps(true);
|
29 | };
|
30 | TokenCoverageChecker.prototype._addNodeTree = function (node) {
|
31 | if (node instanceof DocExcerpt) {
|
32 | this._addSequence(node.content, node);
|
33 | }
|
34 | for (var _i = 0, _a = node.getChildNodes(); _i < _a.length; _i++) {
|
35 | var childNode = _a[_i];
|
36 | this._addNodeTree(childNode);
|
37 | }
|
38 | };
|
39 | TokenCoverageChecker.prototype._addSequence = function (tokenSequence, docNode) {
|
40 | var newTokenAssociation = { docNode: docNode, tokenSequence: tokenSequence };
|
41 | for (var i = tokenSequence.startIndex; i < tokenSequence.endIndex; ++i) {
|
42 | var tokenAssociation = this._tokenAssociations[i];
|
43 | if (tokenAssociation) {
|
44 | throw new Error("Overlapping content encountered between" +
|
45 | (" " + this._formatTokenAssociation(tokenAssociation) + " and") +
|
46 | (" " + this._formatTokenAssociation(newTokenAssociation)));
|
47 | }
|
48 | this._tokenAssociations[i] = newTokenAssociation;
|
49 | }
|
50 | };
|
51 | TokenCoverageChecker.prototype._checkForGaps = function (reportGaps) {
|
52 | var gaps = [];
|
53 | var gapStartIndex = undefined;
|
54 | var tokenAssociationBeforeGap = undefined;
|
55 | var tokens = this._parserContext.tokens;
|
56 | if (tokens[tokens.length - 1].kind !== TokenKind.EndOfInput) {
|
57 | throw new Error('Missing EndOfInput token');
|
58 | }
|
59 | for (var i = 0; i < this._parserContext.tokens.length - 1; ++i) {
|
60 | var tokenAssociation = this._tokenAssociations[i];
|
61 | if (gapStartIndex === undefined) {
|
62 |
|
63 | if (tokenAssociation) {
|
64 | tokenAssociationBeforeGap = tokenAssociation;
|
65 | }
|
66 | else {
|
67 |
|
68 | gapStartIndex = i;
|
69 | }
|
70 | }
|
71 | else {
|
72 |
|
73 | if (tokenAssociation) {
|
74 | var gap = new TokenSequence({
|
75 | parserContext: this._parserContext,
|
76 | startIndex: gapStartIndex,
|
77 | endIndex: i
|
78 | });
|
79 | if (reportGaps) {
|
80 | this._reportGap(gap, tokenAssociationBeforeGap, tokenAssociation);
|
81 | }
|
82 | gaps.push(gap);
|
83 | gapStartIndex = undefined;
|
84 | tokenAssociationBeforeGap = undefined;
|
85 | }
|
86 | }
|
87 | }
|
88 | if (gapStartIndex) {
|
89 | var gap = new TokenSequence({
|
90 | parserContext: this._parserContext,
|
91 | startIndex: gapStartIndex,
|
92 | endIndex: this._parserContext.tokens.length
|
93 | });
|
94 | if (reportGaps) {
|
95 | this._reportGap(gap, tokenAssociationBeforeGap, undefined);
|
96 | }
|
97 | gaps.push(gap);
|
98 | }
|
99 | return gaps;
|
100 | };
|
101 | TokenCoverageChecker.prototype._reportGap = function (gap, tokenAssociationBeforeGap, tokenAssociationAfterGap) {
|
102 | var message = 'Gap encountered';
|
103 | if (tokenAssociationBeforeGap) {
|
104 | message += ' before ' + this._formatTokenAssociation(tokenAssociationBeforeGap);
|
105 | }
|
106 | if (tokenAssociationAfterGap) {
|
107 | message += ' after ' + this._formatTokenAssociation(tokenAssociationAfterGap);
|
108 | }
|
109 | message += ': ' + JSON.stringify(gap.toString());
|
110 | throw new Error(message);
|
111 | };
|
112 | TokenCoverageChecker.prototype._formatTokenAssociation = function (tokenAssociation) {
|
113 | return tokenAssociation.docNode.kind + " (" + JSON.stringify(tokenAssociation.tokenSequence.toString()) + ")";
|
114 | };
|
115 | return TokenCoverageChecker;
|
116 | }());
|
117 | export { TokenCoverageChecker };
|
118 |
|
\ | No newline at end of file |