1 | /* @flow */
|
2 |
|
3 | /**
|
4 | * Based on the comment attachment algorithm used in espree and estraverse.
|
5 | *
|
6 | * Redistribution and use in source and binary forms, with or without
|
7 | * modification, are permitted provided that the following conditions are met:
|
8 | *
|
9 | * * Redistributions of source code must retain the above copyright
|
10 | * notice, this list of conditions and the following disclaimer.
|
11 | * * Redistributions in binary form must reproduce the above copyright
|
12 | * notice, this list of conditions and the following disclaimer in the
|
13 | * documentation and/or other materials provided with the distribution.
|
14 | *
|
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
18 | * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
25 | */
|
26 |
|
27 | ;
|
28 |
|
29 | var _interopRequireDefault = require("babel-runtime/helpers/interop-require-default")["default"];
|
30 |
|
31 | var _index = require("./index");
|
32 |
|
33 | var _index2 = _interopRequireDefault(_index);
|
34 |
|
35 | function last(stack) {
|
36 | return stack[stack.length - 1];
|
37 | }
|
38 |
|
39 | var pp = _index2["default"].prototype;
|
40 |
|
41 | pp.addComment = function (comment) {
|
42 | this.state.trailingComments.push(comment);
|
43 | this.state.leadingComments.push(comment);
|
44 | };
|
45 |
|
46 | pp.processComment = function (node) {
|
47 | if (node.type === "Program" && node.body.length > 0) return;
|
48 |
|
49 | var stack = this.state.commentStack;
|
50 |
|
51 | var lastChild = undefined,
|
52 | trailingComments = undefined,
|
53 | i = undefined;
|
54 |
|
55 | if (this.state.trailingComments.length > 0) {
|
56 | // If the first comment in trailingComments comes after the
|
57 | // current node, then we're good - all comments in the array will
|
58 | // come after the node and so it's safe to add them as official
|
59 | // trailingComments.
|
60 | if (this.state.trailingComments[0].start >= node.end) {
|
61 | trailingComments = this.state.trailingComments;
|
62 | this.state.trailingComments = [];
|
63 | } else {
|
64 | // Otherwise, if the first comment doesn't come after the
|
65 | // current node, that means we have a mix of leading and trailing
|
66 | // comments in the array and that leadingComments contains the
|
67 | // same items as trailingComments. Reset trailingComments to
|
68 | // zero items and we'll handle this by evaluating leadingComments
|
69 | // later.
|
70 | this.state.trailingComments.length = 0;
|
71 | }
|
72 | } else {
|
73 | var lastInStack = last(stack);
|
74 | if (stack.length > 0 && lastInStack.trailingComments && lastInStack.trailingComments[0].start >= node.end) {
|
75 | trailingComments = lastInStack.trailingComments;
|
76 | lastInStack.trailingComments = null;
|
77 | }
|
78 | }
|
79 |
|
80 | // Eating the stack.
|
81 | while (stack.length > 0 && last(stack).start >= node.start) {
|
82 | lastChild = stack.pop();
|
83 | }
|
84 |
|
85 | if (lastChild) {
|
86 | if (lastChild.leadingComments) {
|
87 | if (lastChild !== node && last(lastChild.leadingComments).end <= node.start) {
|
88 | node.leadingComments = lastChild.leadingComments;
|
89 | lastChild.leadingComments = null;
|
90 | } else {
|
91 | // A leading comment for an anonymous class had been stolen by its first ClassMethod,
|
92 | // so this takes back the leading comment.
|
93 | // See also: https://github.com/eslint/espree/issues/158
|
94 | for (i = lastChild.leadingComments.length - 2; i >= 0; --i) {
|
95 | if (lastChild.leadingComments[i].end <= node.start) {
|
96 | node.leadingComments = lastChild.leadingComments.splice(0, i + 1);
|
97 | break;
|
98 | }
|
99 | }
|
100 | }
|
101 | }
|
102 | } else if (this.state.leadingComments.length > 0) {
|
103 | if (last(this.state.leadingComments).end <= node.start) {
|
104 | node.leadingComments = this.state.leadingComments;
|
105 | this.state.leadingComments = [];
|
106 | } else {
|
107 | // https://github.com/eslint/espree/issues/2
|
108 | //
|
109 | // In special cases, such as return (without a value) and
|
110 | // debugger, all comments will end up as leadingComments and
|
111 | // will otherwise be eliminated. This step runs when the
|
112 | // commentStack is empty and there are comments left
|
113 | // in leadingComments.
|
114 | //
|
115 | // This loop figures out the stopping point between the actual
|
116 | // leading and trailing comments by finding the location of the
|
117 | // first comment that comes after the given node.
|
118 | for (i = 0; i < this.state.leadingComments.length; i++) {
|
119 | if (this.state.leadingComments[i].end > node.start) {
|
120 | break;
|
121 | }
|
122 | }
|
123 |
|
124 | // Split the array based on the location of the first comment
|
125 | // that comes after the node. Keep in mind that this could
|
126 | // result in an empty array, and if so, the array must be
|
127 | // deleted.
|
128 | node.leadingComments = this.state.leadingComments.slice(0, i);
|
129 | if (node.leadingComments.length === 0) {
|
130 | node.leadingComments = null;
|
131 | }
|
132 |
|
133 | // Similarly, trailing comments are attached later. The variable
|
134 | // must be reset to null if there are no trailing comments.
|
135 | trailingComments = this.state.leadingComments.slice(i);
|
136 | if (trailingComments.length === 0) {
|
137 | trailingComments = null;
|
138 | }
|
139 | }
|
140 | }
|
141 |
|
142 | if (trailingComments) {
|
143 | if (trailingComments.length && trailingComments[0].start >= node.start && last(trailingComments).end <= node.end) {
|
144 | node.innerComments = trailingComments;
|
145 | } else {
|
146 | node.trailingComments = trailingComments;
|
147 | }
|
148 | }
|
149 |
|
150 | stack.push(node);
|
151 | }; |
\ | No newline at end of file |