Merge "Implement source position retrieval"
diff --git a/doclet_adapter/src/main/java/com/google/doclava/javadoc/DocImpl.java b/doclet_adapter/src/main/java/com/google/doclava/javadoc/DocImpl.java
index 0ad7c6f..029f63a 100644
--- a/doclet_adapter/src/main/java/com/google/doclava/javadoc/DocImpl.java
+++ b/doclet_adapter/src/main/java/com/google/doclava/javadoc/DocImpl.java
@@ -259,6 +259,6 @@
@Override
@Used(implemented = true)
public SourcePosition position() {
- return SourcePositionImpl.STUB;
+ return SourcePositionImpl.create(context, element);
}
}
diff --git a/doclet_adapter/src/main/java/com/google/doclava/javadoc/ExecutableMemberDocImpl.java b/doclet_adapter/src/main/java/com/google/doclava/javadoc/ExecutableMemberDocImpl.java
index 650856f..8cb634e 100644
--- a/doclet_adapter/src/main/java/com/google/doclava/javadoc/ExecutableMemberDocImpl.java
+++ b/doclet_adapter/src/main/java/com/google/doclava/javadoc/ExecutableMemberDocImpl.java
@@ -191,6 +191,6 @@
@Override
@Used(implemented = true)
public SourcePosition position() {
- return SourcePositionImpl.STUB;
+ return SourcePositionImpl.create(context, executableElement);
}
}
diff --git a/doclet_adapter/src/main/java/com/google/doclava/javadoc/SourcePositionImpl.java b/doclet_adapter/src/main/java/com/google/doclava/javadoc/SourcePositionImpl.java
index 7813498..da5533e 100644
--- a/doclet_adapter/src/main/java/com/google/doclava/javadoc/SourcePositionImpl.java
+++ b/doclet_adapter/src/main/java/com/google/doclava/javadoc/SourcePositionImpl.java
@@ -27,16 +27,128 @@
import com.google.doclava.annotation.Used;
import com.sun.javadoc.SourcePosition;
+import com.sun.source.doctree.DocCommentTree;
+import com.sun.source.doctree.DocTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.util.DocSourcePositions;
+import com.sun.source.util.DocTrees;
+import com.sun.source.util.TreePath;
+
import java.io.File;
+import java.io.IOException;
+
+import javax.lang.model.element.Element;
+import javax.tools.JavaFileObject;
+
+import jdk.javadoc.doclet.DocletEnvironment;
class SourcePositionImpl implements SourcePosition {
- public static final SourcePositionImpl STUB = new SourcePositionImpl();
+ public static final SourcePositionImpl UNKNOWN = new SourcePositionImpl();
+
+ private static final int POS_NOT_FOUND = -1;
+ private static final int POS_NULL_SOURCE_POSITIONS = -100;
+ private static final int POS_NULL_COMPILATION_UNIT_TREE = -200;
+ private static final int POS_FAILED = -300;
private final File file;
+ private final int line;
+ private final int column;
- public SourcePositionImpl() {
+
+ static SourcePosition create(Context context, Element element) {
+ return create(context, element, null);
+ }
+
+ static SourcePosition create(Context context, Element element, DocTree docTree) {
+ try {
+ Builder builder = new Builder(context, element, docTree);
+ return builder.build();
+ } catch (Exception e) {
+ return SourcePositionImpl.UNKNOWN;
+ }
+ }
+
+ private static class Builder {
+ private final Context context;
+ private final Element element;
+ private DocTree docTree;
+
+ private boolean initialized = false;
+ private DocTrees docTrees;
+ private TreePath treePath;
+ private DocCommentTree docCommentTree;
+ private CompilationUnitTree compilationUnitTree;
+ private JavaFileObject javaFileObject;
+ private DocSourcePositions sourcePositions;
+
+ Builder(Context context, Element element, DocTree docTree) {
+ this.context = context;
+ this.element = element;
+ this.docTree = docTree;
+ }
+
+ SourcePosition build() {
+ if (!init()) {
+ return SourcePositionImpl.UNKNOWN;
+ }
+ long pos = getSourcePosition();
+ if (pos < 0) {
+ return createPosError(pos);
+ }
+ PositionConverter conv = new PositionConverter(javaFileObject, pos);
+ return new SourcePositionImpl(javaFileObject.getName(), conv.getLine(), conv.getCol());
+ }
+
+ private boolean init() {
+ if (initialized) {
+ return true;
+ }
+ docTrees = context.environment.getDocTrees();
+ treePath = docTrees.getPath(element);
+ if (treePath == null) {
+ return false;
+ }
+ docCommentTree = docTrees.getDocCommentTree(element);
+ if (docCommentTree == null) {
+ return false;
+ }
+ compilationUnitTree = treePath.getCompilationUnit();
+ javaFileObject = compilationUnitTree.getSourceFile();
+ sourcePositions = docTrees.getSourcePositions();
+ if (docTree == null) {
+ docTree = docCommentTree;
+ }
+ initialized = true;
+ return true;
+ }
+
+ private SourcePosition createPosError(long code) {
+ return new SourcePositionImpl(javaFileObject.getName(), (int)code, 0);
+ }
+
+ private long getSourcePosition() {
+ if (sourcePositions == null) {
+ return POS_NULL_SOURCE_POSITIONS;
+ }
+ if (compilationUnitTree == null) {
+ return POS_NULL_COMPILATION_UNIT_TREE;
+ }
+ return sourcePositions.getStartPosition(compilationUnitTree,
+ docCommentTree, docTree);
+ }
+ }
+
+ private SourcePositionImpl() {
this.file = new File(".");
+ this.line = POS_NOT_FOUND;
+ this.column = 0;
+ }
+
+ private SourcePositionImpl(String filename, int line, int column) {
+ this.file = new File(filename);
+ this.line = line;
+ this.column = column;
}
@Override
@@ -48,12 +160,89 @@
@Override
@Used(implemented = true)
public int line() {
- return 0;
+ return line;
}
@Override
@Used(implemented = true)
public int column() {
- return 0;
+ return column;
+ }
+
+ private static class PositionConverter {
+ final JavaFileObject javaFileObject;
+ final long pos;
+ int lineStartAt = -1;
+ int line = -1;
+
+ public PositionConverter(JavaFileObject javaFileObject, long pos) {
+ this.javaFileObject = javaFileObject;
+ this.pos = pos;
+ }
+
+ public int getLine() {
+ if (pos < 0) {
+ return (int) pos;
+ }
+
+ if (!findLine()) {
+ return POS_FAILED;
+ }
+
+ return line;
+ }
+
+ private boolean findLine() {
+ if (line > 0) {
+ return true;
+ }
+ try {
+ char[] buf = loadBuf(javaFileObject);
+ if (pos > buf.length) {
+ return false;
+ }
+ lineStartAt = 0;
+ line = 1;
+
+ for (int idx = 0; idx < buf.length && idx < pos; idx++) {
+ if (isEndOfLine(idx, buf)) {
+ line++;
+ lineStartAt = idx+1;
+ }
+ }
+ return true;
+ } catch (IOException e) {
+ line = -1;
+ lineStartAt = -1;
+ return false;
+ }
+ }
+
+ private char[] loadBuf(JavaFileObject fileObject) throws IOException {
+ CharSequence chars = fileObject.getCharContent(true);
+ return chars.toString().toCharArray();
+ }
+
+ private boolean isEndOfLine(int idx, char[] buf) {
+ if (buf[idx] == '\n') {
+ return true;
+ }
+ if (buf[idx] == '\r' && (idx == buf.length - 1 || buf[idx+1] != '\n')) {
+ return true;
+ }
+ return false;
+ }
+
+ public int getCol() {
+ if (pos < 0) {
+ return -1;
+ }
+
+ if (!findLine()) {
+ return 0;
+ }
+
+ return (int)pos - lineStartAt + 1;
+ }
}
}
diff --git a/doclet_adapter/src/main/java/com/google/doclava/javadoc/TagImpl.java b/doclet_adapter/src/main/java/com/google/doclava/javadoc/TagImpl.java
index 2aea77e..d802a10 100644
--- a/doclet_adapter/src/main/java/com/google/doclava/javadoc/TagImpl.java
+++ b/doclet_adapter/src/main/java/com/google/doclava/javadoc/TagImpl.java
@@ -135,7 +135,7 @@
@Override
@Used(implemented = true)
public SourcePosition position() {
- return SourcePositionImpl.STUB;
+ return SourcePositionImpl.create(context, owner, docTree);
}
private static final SimpleDocTreeVisitor<String, Context> NAME_VISITOR =
diff --git a/src/com/google/doclava/Doclava.java b/src/com/google/doclava/Doclava.java
index e164faa..dfdc428 100644
--- a/src/com/google/doclava/Doclava.java
+++ b/src/com/google/doclava/Doclava.java
@@ -523,8 +523,7 @@
@Override public List<String> getNames() { return names; }
@Override public String getParameters() { return ""; }
@Override public boolean process(String opt, List<String> arguments) {
- // b/270335911: disable warnings as errors until new findings are addressed.
- // Errors.setWarningsAreErrors(true);
+ Errors.setWarningsAreErrors(true);
return true;
}
}