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

Unified Diff: compiler/java/com/google/dart/compiler/parser/DartParserCommentsHelper.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 side-by-side diff with in-line comments
Download patch
Index: compiler/java/com/google/dart/compiler/parser/DartParserCommentsHelper.java
diff --git a/compiler/java/com/google/dart/compiler/parser/DartParserCommentsHelper.java b/compiler/java/com/google/dart/compiler/parser/DartParserCommentsHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..6633dc506207eb6ef82ebfcdd89955c33013006f
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/parser/DartParserCommentsHelper.java
@@ -0,0 +1,232 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.parser;
+
+import com.google.common.collect.Lists;
+import com.google.dart.compiler.DartCompilerListener;
+import com.google.dart.compiler.Source;
+import com.google.dart.compiler.ast.ASTVisitor;
+import com.google.dart.compiler.ast.DartComment;
+import com.google.dart.compiler.ast.DartDeclaration;
+import com.google.dart.compiler.ast.DartField;
+import com.google.dart.compiler.ast.DartMethodDefinition;
+import com.google.dart.compiler.ast.DartNode;
+import com.google.dart.compiler.ast.DartUnit;
+import com.google.dart.compiler.common.SourceInfo;
+import com.google.dart.compiler.metrics.CompilerMetrics;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * A parser for Dart that records comment positions.
+ */
+public class DartParserCommentsHelper {
+
+ static class CommentParserContext extends DartScannerParserContext {
+
+ private List<int[]> commentLocs;
+
+ CommentParserContext(Source source, String code, DartCompilerListener listener,
+ CompilerMetrics metrics) {
+ super(source, code, listener, metrics);
+ }
+
+ List<int[]> getCommentLocs() {
+ return commentLocs;
+ }
+
+ @Override
+ protected DartScanner createScanner(String sourceCode) {
+ commentLocs = Lists.newArrayList();
+ return new CommentScanner(sourceCode);
+ }
+
+ private class CommentScanner extends DartScanner {
+
+ CommentScanner(String sourceCode) {
+ super(sourceCode);
+ }
+
+ @Override
+ protected void recordCommentLocation(int start, int stop, int line, int col) {
+ int size = commentLocs.size();
+ if (size > 0) {
+ // the parser may re-scan lookahead tokens
+ // fortunately, comments are always scanned as comments
+ int[] loc = commentLocs.get(size - 1);
+ if (start <= loc[0] && stop <= loc[1]) {
+ return;
+ }
+ }
+ commentLocs.add(new int[] {start, stop});
+ }
+ }
+ }
+
+ static void addComments(DartUnit unit, Source source, String sourceCode, List<int[]> commentLocs) {
+ for (int[] loc : commentLocs) {
+ int start = loc[0];
+ int length = loc[1] - start;
+ DartComment.Style style = getCommentStyle(sourceCode, start);
+ unit.getComments().add(new DartComment(source, start, length, style));
+ }
+ List<DartComment> comments = unit.getComments();
+ if (comments != null) {
+ assignDartComments(unit, sourceCode, comments);
+ }
+ }
+
+ private static void assignDartComments(DartUnit unit, String sourceCode,
+ List<DartComment> comments) {
+ // Collect the AST nodes in a list.
+ final List<DartNode> astNodes = new ArrayList<DartNode>();
+ unit.accept(new ASTVisitor<DartNode>() {
+ @Override
+ public DartNode visitDeclaration(DartDeclaration<?> node) {
+ astNodes.add(node);
+ // Avoid NPE in visitors because of missing part.
+ try {
+ super.visitDeclaration(node);
+ } catch (NullPointerException e) {
+ }
+ // No result.
+ return null;
+ }
+ });
+
+ // Collect all the nodes in one list.
+ List<DartNode> nodes = new ArrayList<DartNode>();
+
+ nodes.addAll(comments);
+ nodes.addAll(astNodes);
+
+ // Sort the nodes by their position in the source file.
+ Collections.sort(nodes, new Comparator<DartNode>() {
+ @Override
+ public int compare(DartNode node1, DartNode node2) {
+ return node1.getSourceInfo().getOffset() - node2.getSourceInfo().getOffset();
+ }
+ });
+
+ // Assign dart docs to their associated DartDeclarations.
+ for (int i = 0; i < nodes.size(); i++) {
+ DartNode node = nodes.get(i);
+ if (node instanceof DartComment) {
+ DartComment comment = (DartComment) node;
+ // prepare next declaration
+ DartDeclaration<?> decl = null;
+ {
+ int delta = 1;
+ while (i + delta < nodes.size()) {
+ DartNode next = nodes.get(i + delta);
+ // skip all comments
+ if (next instanceof DartComment) {
+ delta++;
+ continue;
+ }
+ // declaration found
+ if (next instanceof DartDeclaration) {
+ decl = (DartDeclaration<?>) next;
+ if (!commentContainedBySibling(comment, decl)) {
+ if (i + 2 < nodes.size()) {
+ decl = adjustDartdocTarget(next, nodes.get(i + 2));
+ }
+ }
+ break;
+ }
+ // something other than declaration
+ break;
+ }
+ }
+ // apply comment to declaration
+ if (decl != null) {
+ String commentStr = sourceCode.substring(comment.getSourceInfo().getOffset(),
+ comment.getSourceInfo().getEnd());
+ // may be @Metadata
+ if (commentStr.contains("@deprecated")) {
+ decl.setMetadata(decl.getMetadata().makeDeprecated());
+ }
+ if (commentStr.contains("@override")) {
+ decl.setMetadata(decl.getMetadata().makeOverride());
+ }
+ // DartDoc
+ if (comment.isDartDoc()) {
+ decl.setDartDoc(comment);
+ }
+ }
+ }
+ }
+ }
+
+ private static DartDeclaration<?> adjustDartdocTarget(DartNode currentNode, DartNode nextNode) {
+ if (currentNode instanceof DartField && nextNode instanceof DartMethodDefinition) {
+ if (currentNode.getSourceInfo().equals(nextNode.getSourceInfo())) {
+ return (DartDeclaration<?>) nextNode;
+ }
+ }
+
+ return (DartDeclaration<?>) currentNode;
+ }
+
+ /**
+ * DartC creates both a DartField and a DartMethodDefinition for getters and setters. They have
+ * the same source location; we want to assign the DartDoc to the method definition and not the
+ * field.
+ */
+ private static boolean commentContainedBySibling(DartComment comment, DartDeclaration<?> node) {
+ for (DartNode child : getChildren(node.getParent())) {
+ if (child != node && !(child instanceof DartComment)) {
+ if (isContainedBy(comment, child)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private static List<DartNode> getChildren(DartNode parent) {
+ final List<DartNode> children = new ArrayList<DartNode>();
+
+ parent.visitChildren(new ASTVisitor<DartNode>() {
+ @Override
+ public DartNode visitNode(DartNode node) {
+ children.add(node);
+ return null;
+ }
+ });
+
+ return children;
+ }
+
+ private static boolean isContainedBy(DartNode node, DartNode containedByNode) {
+ SourceInfo nodeSource = node.getSourceInfo();
+ SourceInfo containedBySource = containedByNode.getSourceInfo();
+ int nodeEnd = nodeSource.getOffset() + nodeSource.getLength();
+ int containedByEnd = containedBySource.getOffset() + containedBySource.getLength();
+ return nodeSource.getOffset() >= containedBySource.getOffset() && nodeEnd <= containedByEnd;
+ }
+
+ /**
+ * Return the style of the comment in the given string.
+ *
+ * @param sourceString the source containing the comment
+ * @param commentStart the location of the comment in the source
+ * @return the style of the comment in the given string
+ */
+ private static DartComment.Style getCommentStyle(String sourceString, int commentStart) {
+ boolean hasMore1 = commentStart + 1 < sourceString.length();
+ boolean hasMore2 = commentStart + 2 < sourceString.length();
+ if (hasMore1 && sourceString.charAt(commentStart + 1) == '/') {
+ return DartComment.Style.END_OF_LINE;
+ } else if (hasMore2 && sourceString.charAt(commentStart + 2) == '*') {
+ return DartComment.Style.DART_DOC;
+ }
+ return DartComment.Style.BLOCK;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698