Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(290)

Side by Side Diff: compiler/java/com/google/dart/compiler/parser/CommentPreservingParser.java

Issue 10661022: Issue 3752. Support for @override annotations (as structured doc comments) (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 package com.google.dart.compiler.parser;
6
7 import com.google.dart.compiler.DartCompilerListener;
8 import com.google.dart.compiler.DartSource;
9 import com.google.dart.compiler.Source;
10 import com.google.dart.compiler.ast.ASTVisitor;
11 import com.google.dart.compiler.ast.DartComment;
12 import com.google.dart.compiler.ast.DartDeclaration;
13 import com.google.dart.compiler.ast.DartField;
14 import com.google.dart.compiler.ast.DartMethodDefinition;
15 import com.google.dart.compiler.ast.DartNode;
16 import com.google.dart.compiler.ast.DartUnit;
17 import com.google.dart.compiler.common.SourceInfo;
18 import com.google.dart.compiler.metrics.CompilerMetrics;
19 import com.google.dart.compiler.util.DartSourceString;
20
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.Comparator;
24 import java.util.List;
25
26 /**
27 * A parser for Dart that records comment positions.
28 */
29 public class CommentPreservingParser extends DartParser {
30
31 private static class CommentParserContext extends DartScannerParserContext {
32
33 private List<int[]> commentLocs;
34 private String source;
35
36 CommentParserContext(Source source, String code,
37 DartCompilerListener listener) {
38 super(source, code, listener);
39 this.source = code;
40 }
41
42 CommentParserContext(Source source, String code,
43 DartCompilerListener listener, CompilerMetrics metrics) {
44 super(source, code, listener, metrics);
45 this.source = code;
46 }
47
48 List<int[]> getCommentLocs() {
49 return commentLocs;
50 }
51
52 @Override
53 protected DartScanner createScanner(String sourceCode) {
54 commentLocs = new ArrayList<int[]>();
55 return this.new CommentScanner(sourceCode);
56 }
57
58 private class CommentScanner extends DartScanner {
59
60 CommentScanner(String sourceCode) {
61 super(sourceCode);
62 }
63
64 @Override
65 protected void recordCommentLocation(int start, int stop, int line, int co l) {
66 int size = commentLocs.size();
67 if (size > 0) {
68 // the parser may re-scan lookahead tokens
69 // fortunately, comments are always scanned as comments
70 int[] loc = commentLocs.get(size - 1);
71 if (start <= loc[0] && stop <= loc[1]) {
72 return;
73 }
74 }
75 commentLocs.add(new int[]{start, stop, line, col});
76 }
77 }
78 }
79
80 /**
81 * Create a parsing context for the comment-recording parser.
82 */
83 public static CommentParserContext createContext(Source source, String code,
84 DartCompilerListener listener) {
85 return new CommentParserContext(source, code, listener);
86 }
87
88 /**
89 * Create a parsing context for the comment-recording parser.
90 */
91 public static CommentParserContext createContext(Source source, String code,
92 DartCompilerListener listener, CompilerMetrics metrics) {
93 return new CommentParserContext(source, code, listener, metrics);
94 }
95
96 private CommentParserContext context;
97 private boolean onlyDartDoc;
98
99 /**
100 * Create a parser on the given <code>code</code> that records comment locatio ns.
101 */
102 public CommentPreservingParser(String code) {
103 this(code, null, false);
104 }
105
106 /**
107 * Create a parser on the given <code>code</code> that records some comment
108 * locations. If <code>onlyDartDoc</code> is <code>true</code> then only
109 * DartDoc comments will be recorded, otherwise all comments will be recorded.
110 * The given <code>listener</code> will be used to inform clients of errors.
111 */
112 public CommentPreservingParser(String code, DartCompilerListener listener,
113 boolean onlyDartDoc) {
114 this(createContext(null, code, listener), onlyDartDoc);
115 }
116
117 /**
118 * Create a parser with the given parsing context <code>context</code>.
119 * If <code>onlyDartDoc</code> is <code>true</code> then only
120 * DartDoc comments will be recorded, otherwise all comments will be recorded.
121 */
122 public CommentPreservingParser(ParserContext context,
123 boolean onlyDartDoc) {
124 super(context, onlyDartDoc);
125 this.context = (CommentParserContext) context;
126 this.onlyDartDoc = onlyDartDoc;
127 }
128
129 @Override
130 public DartUnit parseUnit(DartSource input) {
131 DartUnit unit = super.parseUnit(input);
132
133 String sourceString = context.source;
134 Source source = new DartSourceString(null, sourceString);
135
136 for (int[] loc : context.getCommentLocs()) {
137 DartComment.Style style = getCommentStyle(sourceString, loc[0]);
138 if (!onlyDartDoc || style == DartComment.Style.DART_DOC) {
139 unit.getComments().add(new DartComment(source, loc[0], loc[1] - loc[0], loc[2], loc[3], style));
140 }
141 }
142
143 List<DartComment> comments = unit.getComments();
144
145 if (comments != null) {
146 assignDartComments(unit, comments);
147 }
148
149 return unit;
150 }
151
152 private void assignDartComments(DartUnit unit, List<DartComment> comments) {
153 // Collect the AST nodes in a list.
154 final List<DartNode> astNodes = new ArrayList<DartNode>();
155 unit.accept(new ASTVisitor<DartNode>() {
156 @Override
157 public DartNode visitDeclaration(DartDeclaration<?> node) {
158 astNodes.add(node);
159 return super.visitNode(node);
160 }
161 });
162
163 // Collect all the nodes in one list.
164 List<DartNode> nodes = new ArrayList<DartNode>();
165
166 nodes.addAll(comments);
167 nodes.addAll(astNodes);
168
169 // Sort the nodes by their position in the source file.
170 Collections.sort(nodes, new Comparator<DartNode>() {
171 @Override
172 public int compare(DartNode node1, DartNode node2) {
173 return node1.getSourceInfo().getOffset() - node2.getSourceInfo().getOffs et();
174 }
175 });
176
177 // Assign dart docs to their associated DartDeclarations.
178 for (int i = 0; i < nodes.size(); i++) {
179 DartNode node = nodes.get(i);
180
181 if (node instanceof DartComment) {
182 DartComment comment = (DartComment)node;
183
184 if (comment.isDartDoc() && (i + 1 < nodes.size())) {
185 DartNode next = nodes.get(i + 1);
186
187 if (next instanceof DartDeclaration) {
188 DartDeclaration<?> decl = (DartDeclaration<?>)next;
189
190 if (!commentContainedBySibling(comment, decl)) {
191 // Dartc creates both a DartField and a DartMethodDefinition for g etters and setters.
192 // They have the same source location; we want to assign the dartd oc to the method
193 // definition and not the field.
194 if (i + 2 < nodes.size()) {
195 decl = adjustDartdocTarget(next, nodes.get(i + 2));
196 }
197
198 decl.setDartDoc(comment);
199 }
200 }
201 }
202 }
203 }
204 }
205
206 private DartDeclaration<?> adjustDartdocTarget(DartNode currentNode, DartNode nextNode) {
207 if (currentNode instanceof DartField && nextNode instanceof DartMethodDefini tion) {
208 if (currentNode.getSourceInfo().equals(nextNode.getSourceInfo())) {
209 return (DartDeclaration<?>)nextNode;
210 }
211 }
212
213 return (DartDeclaration<?>)currentNode;
214 }
215
216 private boolean commentContainedBySibling(DartComment comment, DartDeclaration <?> node) {
217 for (DartNode child : getChildren(node.getParent())) {
218 if (child != node && !(child instanceof DartComment)) {
219 if (isContainedBy(comment, child)) {
220 return true;
221 }
222 }
223 }
224
225 return false;
226 }
227
228 private List<DartNode> getChildren(DartNode parent) {
229 final List<DartNode> children = new ArrayList<DartNode>();
230
231 parent.visitChildren(new ASTVisitor<DartNode>() {
232 @Override
233 public DartNode visitNode(DartNode node) {
234 children.add(node);
235 return null;
236 }
237 });
238
239 return children;
240 }
241
242 private static boolean isContainedBy(DartNode node, DartNode containedByNode) {
243 SourceInfo nodeSource = node.getSourceInfo();
244 SourceInfo containedBySource = containedByNode.getSourceInfo();
245 int nodeEnd = nodeSource.getOffset() + nodeSource.getLength();
246 int containedByEnd = containedBySource.getOffset() + containedBySource.getLe ngth();
247 return nodeSource.getOffset() >= containedBySource.getOffset()
248 && nodeEnd <= containedByEnd;
249 }
250
251 /**
252 * Return the style of the comment in the given string.
253 *
254 * @param sourceString the source containing the comment
255 * @param commentStart the location of the comment in the source
256 *
257 * @return the style of the comment in the given string
258 */
259 private DartComment.Style getCommentStyle(String sourceString, int commentStar t) {
260 if (sourceString.charAt(commentStart + 1) == '/') {
261 return DartComment.Style.END_OF_LINE;
262 } else if (sourceString.charAt(commentStart + 2) == '*') {
263 return DartComment.Style.DART_DOC;
264 }
265 return DartComment.Style.BLOCK;
266 }
267 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698