JavacTrees.java revision 3255:7a0c34355149
1139749Simp/*
235388Smjacob * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
335388Smjacob * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4154704Smjacob *
5154704Smjacob * This code is free software; you can redistribute it and/or modify it
635388Smjacob * under the terms of the GNU General Public License version 2 only, as
735388Smjacob * published by the Free Software Foundation.  Oracle designates this
835388Smjacob * particular file as subject to the "Classpath" exception as provided
935388Smjacob * by Oracle in the LICENSE file that accompanied this code.
1035388Smjacob *
1135388Smjacob * This code is distributed in the hope that it will be useful, but WITHOUT
1235388Smjacob * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1366189Smjacob * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1466189Smjacob * version 2 for more details (a copy is included in the LICENSE file that
1535388Smjacob * accompanied this code).
1635388Smjacob *
1735388Smjacob * You should have received a copy of the GNU General Public License version
1835388Smjacob * 2 along with this work; if not, write to the Free Software Foundation,
1935388Smjacob * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2035388Smjacob *
2135388Smjacob * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2235388Smjacob * or visit www.oracle.com if you need additional information or have any
2335388Smjacob * questions.
2435388Smjacob */
2535388Smjacob
2635388Smjacobpackage com.sun.tools.javac.api;
2735388Smjacob
28119418Sobrienimport java.io.FileNotFoundException;
29119418Sobrienimport java.io.IOException;
30119418Sobrienimport java.text.BreakIterator;
31119418Sobrienimport java.util.HashMap;
3235388Smjacobimport java.util.HashSet;
3377365Smjacobimport java.util.Map;
3477365Smjacobimport java.util.Set;
3564176Smjacobimport java.util.regex.Matcher;
3677365Smjacobimport java.util.regex.Pattern;
37100679Smjacob
3877365Smjacobimport javax.annotation.processing.ProcessingEnvironment;
3977365Smjacobimport javax.lang.model.element.AnnotationMirror;
4035388Smjacobimport javax.lang.model.element.AnnotationValue;
4175200Smjacobimport javax.lang.model.element.Element;
42100679Smjacobimport javax.lang.model.element.ElementKind;
43120088Smarkmimport javax.lang.model.element.ExecutableElement;
4499756Smjacobimport javax.lang.model.element.Modifier;
4599756Smjacobimport javax.lang.model.element.NestingKind;
4699756Smjacobimport javax.lang.model.element.PackageElement;
4777365Smjacobimport javax.lang.model.element.TypeElement;
4862498Smjacobimport javax.lang.model.type.DeclaredType;
49155704Smjacobimport javax.lang.model.type.TypeKind;
5049915Smjacobimport javax.lang.model.type.TypeMirror;
5162173Smjacobimport javax.tools.Diagnostic;
5277365Smjacobimport javax.tools.FileObject;
5349915Smjacobimport javax.tools.ForwardingFileObject;
5439235Sgibbsimport javax.tools.JavaCompiler;
5560220Smjacobimport javax.tools.JavaFileManager;
5677365Smjacobimport javax.tools.JavaFileObject;
57126080Sphkimport javax.tools.JavaFileObject.Kind;
58126080Sphkimport javax.tools.StandardLocation;
59111815Sphk
60111815Sphkimport com.sun.source.doctree.DocCommentTree;
6177365Smjacobimport com.sun.source.doctree.DocTree;
6277365Smjacobimport com.sun.source.tree.CatchTree;
6355371Smjacobimport com.sun.source.tree.CompilationUnitTree;
6449915Smjacobimport com.sun.source.tree.Scope;
6539235Sgibbsimport com.sun.source.tree.Tree;
6642131Smjacobimport com.sun.source.util.DocSourcePositions;
6739235Sgibbsimport com.sun.source.util.DocTreePath;
6846972Smjacobimport com.sun.source.util.DocTreeScanner;
6939235Sgibbsimport com.sun.source.util.DocTrees;
7039235Sgibbsimport com.sun.source.util.JavacTask;
7146972Smjacobimport com.sun.source.util.TreePath;
7246972Smjacobimport com.sun.tools.javac.code.Flags;
7339235Sgibbsimport com.sun.tools.javac.code.Scope.NamedImportScope;
7439235Sgibbsimport com.sun.tools.javac.code.Scope.StarImportScope;
7546972Smjacobimport com.sun.tools.javac.code.Scope.WriteableScope;
7639235Sgibbsimport com.sun.tools.javac.code.Symbol;
7746972Smjacobimport com.sun.tools.javac.code.Symbol.ClassSymbol;
7846972Smjacobimport com.sun.tools.javac.code.Symbol.MethodSymbol;
7946972Smjacobimport com.sun.tools.javac.code.Symbol.PackageSymbol;
8046972Smjacobimport com.sun.tools.javac.code.Symbol.TypeSymbol;
8146972Smjacobimport com.sun.tools.javac.code.Symbol.VarSymbol;
8246972Smjacobimport com.sun.tools.javac.code.Symtab;
8346972Smjacobimport com.sun.tools.javac.code.Type;
8452349Smjacobimport com.sun.tools.javac.code.Type.ArrayType;
8539235Sgibbsimport com.sun.tools.javac.code.Type.ClassType;
8639235Sgibbsimport com.sun.tools.javac.code.Type.ErrorType;
8739235Sgibbsimport com.sun.tools.javac.code.Type.UnionClassType;
8839235Sgibbsimport com.sun.tools.javac.code.Types;
8939235Sgibbsimport com.sun.tools.javac.code.Types.TypeRelation;
9046972Smjacobimport com.sun.tools.javac.comp.Attr;
9139235Sgibbsimport com.sun.tools.javac.comp.AttrContext;
9279336Smjacobimport com.sun.tools.javac.comp.Enter;
9346972Smjacobimport com.sun.tools.javac.comp.Env;
9473245Smjacobimport com.sun.tools.javac.comp.MemberEnter;
9546972Smjacobimport com.sun.tools.javac.comp.Resolve;
9639235Sgibbsimport com.sun.tools.javac.file.BaseFileManager;
9779336Smjacobimport com.sun.tools.javac.model.JavacElements;
9839235Sgibbsimport com.sun.tools.javac.parser.DocCommentParser;
9939235Sgibbsimport com.sun.tools.javac.parser.ParserFactory;
10079336Smjacobimport com.sun.tools.javac.parser.Tokens.Comment;
10162498Smjacobimport com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
10262498Smjacobimport com.sun.tools.javac.processing.JavacProcessingEnvironment;
10362498Smjacobimport com.sun.tools.javac.tree.DCTree;
10479336Smjacobimport com.sun.tools.javac.tree.DCTree.DCBlockTag;
10562498Smjacobimport com.sun.tools.javac.tree.DCTree.DCDocComment;
10679336Smjacobimport com.sun.tools.javac.tree.DCTree.DCEndPosTree;
10779336Smjacobimport com.sun.tools.javac.tree.DCTree.DCErroneous;
10869597Smjacobimport com.sun.tools.javac.tree.DCTree.DCIdentifier;
10969597Smjacobimport com.sun.tools.javac.tree.DCTree.DCParam;
11062498Smjacobimport com.sun.tools.javac.tree.DCTree.DCReference;
11162498Smjacobimport com.sun.tools.javac.tree.DCTree.DCText;
11262498Smjacobimport com.sun.tools.javac.tree.DocCommentTable;
11346972Smjacobimport com.sun.tools.javac.tree.DocTreeMaker;
11446972Smjacobimport com.sun.tools.javac.tree.EndPosTable;
11579336Smjacobimport com.sun.tools.javac.tree.JCTree;
11639235Sgibbsimport com.sun.tools.javac.tree.JCTree.JCBlock;
11739235Sgibbsimport com.sun.tools.javac.tree.JCTree.JCCatch;
11839235Sgibbsimport com.sun.tools.javac.tree.JCTree.JCClassDecl;
11946972Smjacobimport com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
12039235Sgibbsimport com.sun.tools.javac.tree.JCTree.JCExpression;
12146972Smjacobimport com.sun.tools.javac.tree.JCTree.JCIdent;
12246972Smjacobimport com.sun.tools.javac.tree.JCTree.JCMethodDecl;
12377365Smjacobimport com.sun.tools.javac.tree.JCTree.JCVariableDecl;
12479336Smjacobimport com.sun.tools.javac.tree.TreeCopier;
12539235Sgibbsimport com.sun.tools.javac.tree.TreeInfo;
12639235Sgibbsimport com.sun.tools.javac.tree.TreeMaker;
12739235Sgibbsimport com.sun.tools.javac.util.Abort;
12846972Smjacobimport com.sun.tools.javac.util.Assert;
12939235Sgibbsimport com.sun.tools.javac.util.Context;
13039235Sgibbsimport com.sun.tools.javac.util.DefinedBy;
13143420Smjacobimport com.sun.tools.javac.util.DefinedBy.Api;
13246972Smjacobimport com.sun.tools.javac.util.DiagnosticSource;
13339235Sgibbsimport com.sun.tools.javac.util.JCDiagnostic;
13479336Smjacobimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
13546972Smjacobimport com.sun.tools.javac.util.List;
13646972Smjacobimport com.sun.tools.javac.util.ListBuffer;
13777365Smjacobimport com.sun.tools.javac.util.Log;
13877365Smjacobimport com.sun.tools.javac.util.Name;
13977365Smjacobimport com.sun.tools.javac.util.Names;
14077365Smjacobimport com.sun.tools.javac.util.Pair;
14177365Smjacobimport com.sun.tools.javac.util.Position;
14279336Smjacob
14379336Smjacobimport static com.sun.tools.javac.code.Kinds.Kind.*;
14477365Smjacobimport static com.sun.tools.javac.code.TypeTag.*;
14577365Smjacob
146104354Sscottl/**
14777365Smjacob * Provides an implementation of Trees.
14877365Smjacob *
14977365Smjacob * <p><b>This is NOT part of any supported API.
15077365Smjacob * If you write code that depends on this, you do so at your own
15179336Smjacob * risk.  This code and its internal interfaces are subject to change
15279336Smjacob * or deletion without notice.</b></p>
15377365Smjacob *
15477365Smjacob * @author Peter von der Ah&eacute;
15579338Smjacob */
15677365Smjacobpublic class JavacTrees extends DocTrees {
15739235Sgibbs
15877365Smjacob    // in a world of a single context per compilation, these would all be final
15946972Smjacob    private Resolve resolve;
16046972Smjacob    private Enter enter;
16146972Smjacob    private Log log;
16254671Smjacob    private MemberEnter memberEnter;
16379336Smjacob    private Attr attr;
16446972Smjacob    private TreeMaker treeMaker;
16573245Smjacob    private JavacElements elements;
16646972Smjacob    private JavacTaskImpl javacTaskImpl;
16746972Smjacob    private Names names;
16846972Smjacob    private Types types;
16946972Smjacob    private DocTreeMaker docTreeMaker;
17077365Smjacob    private BreakIterator breakIterator;
17146972Smjacob    private JavaFileManager fileManager;
17246972Smjacob    private ParserFactory parser;
17346972Smjacob    private Symtab syms;
17446972Smjacob    private Map<JavaFileObject, PackageSymbol> javaFileObjectToPackageMap;
17546972Smjacob
17646972Smjacob    // called reflectively from Trees.instance(CompilationTask task)
17777365Smjacob    public static JavacTrees instance(JavaCompiler.CompilationTask task) {
17879336Smjacob        if (!(task instanceof BasicJavacTask))
17946972Smjacob            throw new IllegalArgumentException();
18046972Smjacob        return instance(((BasicJavacTask)task).getContext());
18146972Smjacob    }
18246972Smjacob
18346972Smjacob    // called reflectively from Trees.instance(ProcessingEnvironment env)
18446972Smjacob    public static JavacTrees instance(ProcessingEnvironment env) {
18546972Smjacob        if (!(env instanceof JavacProcessingEnvironment))
18646972Smjacob            throw new IllegalArgumentException();
18746972Smjacob        return instance(((JavacProcessingEnvironment)env).getContext());
18877365Smjacob    }
18979336Smjacob
19046972Smjacob    public static JavacTrees instance(Context context) {
19146972Smjacob        JavacTrees instance = context.get(JavacTrees.class);
19246972Smjacob        if (instance == null)
19346972Smjacob            instance = new JavacTrees(context);
19446972Smjacob        return instance;
19546972Smjacob    }
19646972Smjacob
19746972Smjacob    protected JavacTrees(Context context) {
19846972Smjacob        javaFileObjectToPackageMap = new HashMap<>();
19979336Smjacob        this.breakIterator = null;
20046972Smjacob        context.put(JavacTrees.class, this);
20146972Smjacob        init(context);
20246972Smjacob    }
20377365Smjacob
20477365Smjacob    public void updateContext(Context context) {
20577365Smjacob        init(context);
20677365Smjacob    }
20777365Smjacob
20877365Smjacob    private void init(Context context) {
20977365Smjacob        attr = Attr.instance(context);
21072347Smjacob        enter = Enter.instance(context);
21172347Smjacob        elements = JavacElements.instance(context);
21272347Smjacob        log = Log.instance(context);
21372347Smjacob        resolve = Resolve.instance(context);
21455371Smjacob        treeMaker = TreeMaker.instance(context);
21555371Smjacob        memberEnter = MemberEnter.instance(context);
21655371Smjacob        names = Names.instance(context);
21755371Smjacob        types = Types.instance(context);
21855371Smjacob        docTreeMaker = DocTreeMaker.instance(context);
21955371Smjacob        parser = ParserFactory.instance(context);
22055371Smjacob        syms = Symtab.instance(context);
22155371Smjacob        fileManager = context.get(JavaFileManager.class);
22249915Smjacob        JavacTask t = context.get(JavacTask.class);
22377365Smjacob        if (t instanceof JavacTaskImpl)
22439235Sgibbs            javacTaskImpl = (JavacTaskImpl) t;
22539235Sgibbs    }
226155228Smjacob
22799598Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
22899598Smjacob    public BreakIterator getBreakIterator() {
22999598Smjacob        return breakIterator;
23099598Smjacob    }
23199598Smjacob
23299598Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
23399598Smjacob    public DocSourcePositions getSourcePositions() {
23499598Smjacob        return new DocSourcePositions() {
23599598Smjacob                @Override @DefinedBy(Api.COMPILER_TREE)
23699598Smjacob                public long getStartPosition(CompilationUnitTree file, Tree tree) {
23799598Smjacob                    return TreeInfo.getStartPos((JCTree) tree);
23899598Smjacob                }
23999598Smjacob
24099598Smjacob                @Override @DefinedBy(Api.COMPILER_TREE)
24177365Smjacob                public long getEndPosition(CompilationUnitTree file, Tree tree) {
242130585Sphk                    EndPosTable endPosTable = ((JCCompilationUnit) file).endPositions;
24377365Smjacob                    return TreeInfo.getEndPos((JCTree) tree, endPosTable);
24477365Smjacob                }
245125549Smjacob
24677365Smjacob                @Override @DefinedBy(Api.COMPILER_TREE)
24777365Smjacob                public long getStartPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) {
24877365Smjacob                    return ((DCTree) tree).getSourcePosition((DCDocComment) comment);
24977365Smjacob                }
25077365Smjacob                @Override  @DefinedBy(Api.COMPILER_TREE) @SuppressWarnings("fallthrough")
25177365Smjacob                public long getEndPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) {
25277365Smjacob                    DCDocComment dcComment = (DCDocComment) comment;
25377365Smjacob                    if (tree instanceof DCEndPosTree) {
25477365Smjacob                        int endPos = ((DCEndPosTree) tree).getEndPos(dcComment);
25577365Smjacob
25677365Smjacob                        if (endPos != Position.NOPOS) {
25777365Smjacob                            return endPos;
25890813Smjacob                        }
25990813Smjacob                    }
26090813Smjacob                    int correction = 0;
261155704Smjacob                    switch (tree.getKind()) {
26290813Smjacob                        case TEXT:
26390813Smjacob                            DCText text = (DCText) tree;
26490813Smjacob
26590813Smjacob                            return dcComment.comment.getSourcePos(text.pos + text.text.length());
26690813Smjacob                        case ERRONEOUS:
26790813Smjacob                            DCErroneous err = (DCErroneous) tree;
26890813Smjacob
26990813Smjacob                            return dcComment.comment.getSourcePos(err.pos + err.body.length());
27090813Smjacob                        case IDENTIFIER:
27190813Smjacob                            DCIdentifier ident = (DCIdentifier) tree;
27290813Smjacob
27390813Smjacob                            return dcComment.comment.getSourcePos(ident.pos + (ident.name != names.error ? ident.name.length() : 0));
27490813Smjacob                        case PARAM:
27590813Smjacob                            DCParam param = (DCParam) tree;
27690813Smjacob
27790813Smjacob                            if (param.isTypeParameter && param.getDescription().isEmpty()) {
27890813Smjacob                                correction = 1;
27990813Smjacob                            }
28090813Smjacob                        case AUTHOR: case DEPRECATED: case RETURN: case SEE:
28190813Smjacob                        case SERIAL: case SERIAL_DATA: case SERIAL_FIELD: case SINCE:
28290813Smjacob                        case THROWS: case UNKNOWN_BLOCK_TAG: case VERSION: {
28390813Smjacob                            DocTree last = getLastChild(tree);
28490813Smjacob
28590813Smjacob                            if (last != null) {
28699598Smjacob                                return getEndPosition(file, comment, last) + correction;
28790813Smjacob                            }
28890813Smjacob
28990813Smjacob                            DCBlockTag block = (DCBlockTag) tree;
29090813Smjacob
29190813Smjacob                            return dcComment.comment.getSourcePos(block.pos + block.getTagName().length() + 1);
29290813Smjacob                        }
29377365Smjacob                        default:
29477365Smjacob                            DocTree last = getLastChild(tree);
29577365Smjacob
29677365Smjacob                            if (last != null) {
29777365Smjacob                                return getEndPosition(file, comment, last);
29877365Smjacob                            }
29977365Smjacob                            break;
30077365Smjacob                    }
301125549Smjacob
302125549Smjacob                    return Position.NOPOS;
303125549Smjacob                }
304125549Smjacob            };
305125549Smjacob    }
306125549Smjacob
307125549Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
308125549Smjacob    public DocTreeMaker getDocTreeFactory() {
309125549Smjacob        return docTreeMaker;
310125549Smjacob    }
311125549Smjacob
312125549Smjacob    private DocTree getLastChild(DocTree tree) {
313125549Smjacob        final DocTree[] last = new DocTree[] {null};
31477365Smjacob
31577365Smjacob        tree.accept(new DocTreeScanner<Void, Void>() {
31677365Smjacob            @Override @DefinedBy(Api.COMPILER_TREE)
31777365Smjacob            public Void scan(DocTree node, Void p) {
31877365Smjacob                if (node != null) last[0] = node;
31977365Smjacob                return null;
32091036Smjacob            }
32177365Smjacob        }, null);
32277365Smjacob
32377365Smjacob        return last[0];
32477365Smjacob    }
32577365Smjacob
32677365Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
32777365Smjacob    public JCClassDecl getTree(TypeElement element) {
32877365Smjacob        return (JCClassDecl) getTree((Element) element);
32977365Smjacob    }
33077365Smjacob
33177365Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
33277365Smjacob    public JCMethodDecl getTree(ExecutableElement method) {
33377365Smjacob        return (JCMethodDecl) getTree((Element) method);
33477365Smjacob    }
33577365Smjacob
33677365Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
33777365Smjacob    public JCTree getTree(Element element) {
33877365Smjacob        return getTree(element, null);
33977365Smjacob    }
34077365Smjacob
34177365Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
34277365Smjacob    public JCTree getTree(Element e, AnnotationMirror a) {
34377365Smjacob        return getTree(e, a, null);
34477365Smjacob    }
34577365Smjacob
34677365Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
34777365Smjacob    public JCTree getTree(Element e, AnnotationMirror a, AnnotationValue v) {
34877365Smjacob        Pair<JCTree, JCCompilationUnit> treeTopLevel = elements.getTreeAndTopLevel(e, a, v);
34977365Smjacob        if (treeTopLevel == null)
35077365Smjacob            return null;
35177365Smjacob        return treeTopLevel.fst;
35277365Smjacob    }
35377365Smjacob
354156040Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
35577365Smjacob    public TreePath getPath(CompilationUnitTree unit, Tree node) {
35677365Smjacob        return TreePath.getPath(unit, node);
35777365Smjacob    }
35877365Smjacob
35977365Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
36077365Smjacob    public TreePath getPath(Element e) {
36177365Smjacob        return getPath(e, null, null);
36277365Smjacob    }
36377365Smjacob
36477365Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
36577365Smjacob    public TreePath getPath(Element e, AnnotationMirror a) {
36688855Smjacob        return getPath(e, a, null);
36788855Smjacob    }
36888855Smjacob
36988855Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
37088855Smjacob    public TreePath getPath(Element e, AnnotationMirror a, AnnotationValue v) {
37188855Smjacob        final Pair<JCTree, JCCompilationUnit> treeTopLevel = elements.getTreeAndTopLevel(e, a, v);
37288855Smjacob        if (treeTopLevel == null)
37388855Smjacob            return null;
37488855Smjacob        return TreePath.getPath(treeTopLevel.snd, treeTopLevel.fst);
37588855Smjacob    }
37688855Smjacob
37788855Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
37888855Smjacob    public Symbol getElement(TreePath path) {
37988855Smjacob        JCTree tree = (JCTree) path.getLeaf();
38088855Smjacob        Symbol sym = TreeInfo.symbolFor(tree);
38188855Smjacob        if (sym == null) {
38288855Smjacob            if (TreeInfo.isDeclaration(tree)) {
38388855Smjacob                for (TreePath p = path; p != null; p = p.getParentPath()) {
38488855Smjacob                    JCTree t = (JCTree) p.getLeaf();
38588855Smjacob                    if (t.hasTag(JCTree.Tag.CLASSDEF)) {
38688855Smjacob                        JCClassDecl ct = (JCClassDecl) t;
38788855Smjacob                        if (ct.sym != null) {
38888855Smjacob                            if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) {
38988855Smjacob                                attr.attribClass(ct.pos(), ct.sym);
39088855Smjacob                                sym = TreeInfo.symbolFor(tree);
39188855Smjacob                            }
39288855Smjacob                            break;
39388855Smjacob                        }
39488855Smjacob                    }
39588855Smjacob                }
39688855Smjacob            }
39788855Smjacob        }
39888855Smjacob        return sym;
39988855Smjacob    }
40098289Smjacob
40198289Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
40298289Smjacob    public Element getElement(DocTreePath path) {
40398289Smjacob        DocTree forTree = path.getLeaf();
40498289Smjacob        if (forTree instanceof DCReference)
405124892Smjacob            return attributeDocReference(path.getTreePath(), ((DCReference) forTree));
406124892Smjacob        if (forTree instanceof DCIdentifier) {
407124892Smjacob            if (path.getParentPath().getLeaf() instanceof DCParam) {
40898289Smjacob                return attributeParamIdentifier(path.getTreePath(), (DCParam) path.getParentPath().getLeaf());
40998289Smjacob            }
41098289Smjacob        }
41198289Smjacob        return null;
412120013Smjacob    }
413120013Smjacob
414120013Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
415120013Smjacob    public java.util.List<DocTree> getFirstSentence(java.util.List<? extends DocTree> list) {
41698289Smjacob        return docTreeMaker.getFirstSentence(list);
41798289Smjacob    }
41898289Smjacob
41998289Smjacob    private Symbol attributeDocReference(TreePath path, DCReference ref) {
42099598Smjacob        Env<AttrContext> env = getAttrContext(path);
42199598Smjacob
42299598Smjacob        Log.DeferredDiagnosticHandler deferredDiagnosticHandler =
42399598Smjacob                new Log.DeferredDiagnosticHandler(log);
42499598Smjacob        try {
42599598Smjacob            final TypeSymbol tsym;
42699598Smjacob            final Name memberName;
42799598Smjacob            if (ref.qualifierExpression == null) {
42899598Smjacob                tsym = env.enclClass.sym;
42999598Smjacob                memberName = (Name) ref.memberName;
43099598Smjacob            } else {
43199598Smjacob                // newSeeTree if the qualifierExpression is a type or package name.
43299598Smjacob                // javac does not provide the exact method required, so
43399598Smjacob                // we first check if qualifierExpression identifies a type,
43499598Smjacob                // and if not, then we check to see if it identifies a package.
43599598Smjacob                Type t = attr.attribType(ref.qualifierExpression, env);
43699598Smjacob                if (t.isErroneous()) {
43799598Smjacob                    if (ref.memberName == null) {
43899598Smjacob                        // Attr/Resolve assume packages exist and create symbols as needed
43999598Smjacob                        // so use getPackageElement to restrict search to existing packages
44099598Smjacob                        PackageSymbol pck = elements.getPackageElement(ref.qualifierExpression.toString());
44199598Smjacob                        if (pck != null) {
44299598Smjacob                            return pck;
44399598Smjacob                        } else if (ref.qualifierExpression.hasTag(JCTree.Tag.IDENT)) {
44499598Smjacob                            // fixup:  allow "identifier" instead of "#identifier"
44599598Smjacob                            // for compatibility with javadoc
44699598Smjacob                            tsym = env.enclClass.sym;
44799598Smjacob                            memberName = ((JCIdent) ref.qualifierExpression).name;
44899598Smjacob                        } else
44999598Smjacob                            return null;
45099598Smjacob                    } else {
45199598Smjacob                        return null;
45299598Smjacob                    }
45399598Smjacob                } else {
45499598Smjacob                    tsym = t.tsym;
45599598Smjacob                    memberName = (Name) ref.memberName;
456155704Smjacob                }
45799598Smjacob            }
45899598Smjacob
45999598Smjacob            if (memberName == null)
46099598Smjacob                return tsym;
46199598Smjacob
46299598Smjacob            final List<Type> paramTypes;
46399598Smjacob            if (ref.paramTypes == null)
46499598Smjacob                paramTypes = null;
46599598Smjacob            else {
46699598Smjacob                ListBuffer<Type> lb = new ListBuffer<>();
46799598Smjacob                for (List<JCTree> l = (List<JCTree>) ref.paramTypes; l.nonEmpty(); l = l.tail) {
46899598Smjacob                    JCTree tree = l.head;
46999598Smjacob                    Type t = attr.attribType(tree, env);
47099598Smjacob                    lb.add(t);
47199598Smjacob                }
47299598Smjacob                paramTypes = lb.toList();
47399598Smjacob            }
47499598Smjacob
47599598Smjacob            ClassSymbol sym = (ClassSymbol) types.cvarUpperBound(tsym.type).tsym;
47699598Smjacob
47799598Smjacob            Symbol msym = (memberName == sym.name)
47899598Smjacob                    ? findConstructor(sym, paramTypes)
47999598Smjacob                    : findMethod(sym, memberName, paramTypes);
48099598Smjacob            if (paramTypes != null) {
48199598Smjacob                // explicit (possibly empty) arg list given, so cannot be a field
48299598Smjacob                return msym;
48399598Smjacob            }
48499598Smjacob
48599598Smjacob            VarSymbol vsym = (ref.paramTypes != null) ? null : findField(sym, memberName);
48699598Smjacob            // prefer a field over a method with no parameters
48799598Smjacob            if (vsym != null &&
48899598Smjacob                    (msym == null ||
48999598Smjacob                        types.isSubtypeUnchecked(vsym.enclClass().asType(), msym.enclClass().asType()))) {
49099598Smjacob                return vsym;
49199598Smjacob            } else {
49299598Smjacob                return msym;
49399598Smjacob            }
49499598Smjacob        } catch (Abort e) { // may be thrown by Check.completionError in case of bad class file
49599598Smjacob            return null;
49699598Smjacob        } finally {
49799598Smjacob            log.popDiagnosticHandler(deferredDiagnosticHandler);
49899598Smjacob        }
49999598Smjacob    }
50099598Smjacob
50199598Smjacob    private Symbol attributeParamIdentifier(TreePath path, DCParam ptag) {
50299598Smjacob        Symbol javadocSymbol = getElement(path);
50399598Smjacob        if (javadocSymbol == null)
50499598Smjacob            return null;
50599598Smjacob        ElementKind kind = javadocSymbol.getKind();
50699598Smjacob        List<? extends Symbol> params = List.nil();
50799598Smjacob        if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) {
508151834Smjacob            MethodSymbol ee = (MethodSymbol) javadocSymbol;
509151834Smjacob            params = ptag.isTypeParameter()
510151834Smjacob                    ? ee.getTypeParameters()
511151834Smjacob                    : ee.getParameters();
512155704Smjacob        } else if (kind.isClass() || kind.isInterface()) {
513151834Smjacob            ClassSymbol te = (ClassSymbol) javadocSymbol;
514151834Smjacob            params = te.getTypeParameters();
515151834Smjacob        }
516151834Smjacob
517151834Smjacob        for (Symbol param : params) {
518151834Smjacob            if (param.getSimpleName() == ptag.getName().getName()) {
519151834Smjacob                return param;
520151834Smjacob            }
521151834Smjacob        }
522154704Smjacob        return null;
523154704Smjacob    }
524154704Smjacob
525154704Smjacob    /** @see com.sun.tools.javadoc.ClassDocImpl#findField */
526151834Smjacob    private VarSymbol findField(ClassSymbol tsym, Name fieldName) {
527151834Smjacob        return searchField(tsym, fieldName, new HashSet<>());
528151834Smjacob    }
529154704Smjacob
530151834Smjacob    /** @see com.sun.tools.javadoc.ClassDocImpl#searchField */
531151834Smjacob    private VarSymbol searchField(ClassSymbol tsym, Name fieldName, Set<ClassSymbol> searched) {
532151834Smjacob        if (searched.contains(tsym)) {
533151834Smjacob            return null;
534154704Smjacob        }
535151834Smjacob        searched.add(tsym);
536151834Smjacob
537151834Smjacob        for (Symbol sym : tsym.members().getSymbolsByName(fieldName)) {
538151834Smjacob            if (sym.kind == VAR) {
539154704Smjacob                return (VarSymbol)sym;
540151834Smjacob            }
541151834Smjacob        }
542151834Smjacob
543151834Smjacob        //### If we found a VarSymbol above, but which did not pass
544151834Smjacob        //### the modifier filter, we should return failure here!
545154704Smjacob
546151834Smjacob        ClassSymbol encl = tsym.owner.enclClass();
547151834Smjacob        if (encl != null) {
548151834Smjacob            VarSymbol vsym = searchField(encl, fieldName, searched);
549151834Smjacob            if (vsym != null) {
550151834Smjacob                return vsym;
551154704Smjacob            }
552151834Smjacob        }
553151834Smjacob
554151834Smjacob        // search superclass
555151834Smjacob        Type superclass = tsym.getSuperclass();
556151834Smjacob        if (superclass.tsym != null) {
557151834Smjacob            VarSymbol vsym = searchField((ClassSymbol) superclass.tsym, fieldName, searched);
558151834Smjacob            if (vsym != null) {
559151834Smjacob                return vsym;
560151834Smjacob            }
561151834Smjacob        }
562151834Smjacob
563151834Smjacob        // search interfaces
564151834Smjacob        List<Type> intfs = tsym.getInterfaces();
565151834Smjacob        for (List<Type> l = intfs; l.nonEmpty(); l = l.tail) {
566151834Smjacob            Type intf = l.head;
567151834Smjacob            if (intf.isErroneous()) continue;
568151834Smjacob            VarSymbol vsym = searchField((ClassSymbol) intf.tsym, fieldName, searched);
569151834Smjacob            if (vsym != null) {
570151834Smjacob                return vsym;
57177365Smjacob            }
57277365Smjacob        }
57377365Smjacob
57477365Smjacob        return null;
57577365Smjacob    }
57677365Smjacob
57762498Smjacob    /** @see com.sun.tools.javadoc.ClassDocImpl#findConstructor */
57862498Smjacob    MethodSymbol findConstructor(ClassSymbol tsym, List<Type> paramTypes) {
57962498Smjacob        for (Symbol sym : tsym.members().getSymbolsByName(names.init)) {
58062498Smjacob            if (sym.kind == MTH) {
58172347Smjacob                if (hasParameterTypes((MethodSymbol) sym, paramTypes)) {
58272347Smjacob                    return (MethodSymbol) sym;
583134224Smjacob                }
58472347Smjacob            }
585134224Smjacob        }
58672347Smjacob        return null;
58762498Smjacob    }
58862498Smjacob
58962498Smjacob    /** @see com.sun.tools.javadoc.ClassDocImpl#findMethod */
59055371Smjacob    private MethodSymbol findMethod(ClassSymbol tsym, Name methodName, List<Type> paramTypes) {
59155371Smjacob        return searchMethod(tsym, methodName, paramTypes, new HashSet<>());
59255371Smjacob    }
59355371Smjacob
59455371Smjacob    /** @see com.sun.tools.javadoc.ClassDocImpl#searchMethod */
59555371Smjacob    private MethodSymbol searchMethod(ClassSymbol tsym, Name methodName,
59655371Smjacob                                       List<Type> paramTypes, Set<ClassSymbol> searched) {
597155228Smjacob        //### Note that this search is not necessarily what the compiler would do!
598155228Smjacob
599155228Smjacob        // do not match constructors
600155228Smjacob        if (methodName == names.init)
601155228Smjacob            return null;
60255371Smjacob
60375200Smjacob        if (searched.contains(tsym))
60455371Smjacob            return null;
605125597Smjacob        searched.add(tsym);
606125597Smjacob
60755371Smjacob        // search current class
60875200Smjacob
60975200Smjacob        //### Using modifier filter here isn't really correct,
61075200Smjacob        //### but emulates the old behavior.  Instead, we should
61155371Smjacob        //### apply the normal rules of visibility and inheritance.
61255371Smjacob
61355371Smjacob        if (paramTypes == null) {
61455371Smjacob            // If no parameters specified, we are allowed to return
61598289Smjacob            // any method with a matching name.  In practice, the old
61698289Smjacob            // code returned the first method, which is now the last!
61755371Smjacob            // In order to provide textually identical results, we
618155228Smjacob            // attempt to emulate the old behavior.
61975200Smjacob            MethodSymbol lastFound = null;
62055371Smjacob            for (Symbol sym : tsym.members().getSymbolsByName(methodName)) {
62155371Smjacob                if (sym.kind == MTH) {
62275200Smjacob                    if (sym.name == methodName) {
62375200Smjacob                        lastFound = (MethodSymbol)sym;
62455371Smjacob                    }
62555371Smjacob                }
62655371Smjacob            }
62775200Smjacob            if (lastFound != null) {
62855371Smjacob                return lastFound;
62955371Smjacob            }
63055371Smjacob        } else {
63155371Smjacob            for (Symbol sym : tsym.members().getSymbolsByName(methodName)) {
63255371Smjacob                if (sym != null &&
63355371Smjacob                    sym.kind == MTH) {
634155228Smjacob                    if (hasParameterTypes((MethodSymbol) sym, paramTypes)) {
63575200Smjacob                        return (MethodSymbol) sym;
63655371Smjacob                    }
63775200Smjacob                }
63875200Smjacob            }
63975200Smjacob        }
64075200Smjacob
64175200Smjacob        //### If we found a MethodSymbol above, but which did not pass
64275200Smjacob        //### the modifier filter, we should return failure here!
64375200Smjacob
64475200Smjacob        // search superclass
64575200Smjacob        Type superclass = tsym.getSuperclass();
64675200Smjacob        if (superclass.tsym != null) {
64755371Smjacob            MethodSymbol msym = searchMethod((ClassSymbol) superclass.tsym, methodName, paramTypes, searched);
64855371Smjacob            if (msym != null) {
64955371Smjacob                return msym;
65055371Smjacob            }
65155371Smjacob        }
65255371Smjacob
653155228Smjacob        // search interfaces
65475200Smjacob        List<Type> intfs = tsym.getInterfaces();
65555371Smjacob        for (List<Type> l = intfs; l.nonEmpty(); l = l.tail) {
65683028Smjacob            Type intf = l.head;
65755371Smjacob            if (intf.isErroneous()) continue;
65855371Smjacob            MethodSymbol msym = searchMethod((ClassSymbol) intf.tsym, methodName, paramTypes, searched);
65983028Smjacob            if (msym != null) {
66082689Smjacob                return msym;
66182689Smjacob            }
66282689Smjacob        }
66382689Smjacob
664125597Smjacob        // search enclosing class
66555371Smjacob        ClassSymbol encl = tsym.owner.enclClass();
66675200Smjacob        if (encl != null) {
66783028Smjacob            MethodSymbol msym = searchMethod(encl, methodName, paramTypes, searched);
66883028Smjacob            if (msym != null) {
66983028Smjacob                return msym;
67055371Smjacob            }
67155371Smjacob        }
67255371Smjacob
67375200Smjacob        return null;
67455371Smjacob    }
67555371Smjacob
67655371Smjacob    /** @see com.sun.tools.javadoc.ClassDocImpl */
67755371Smjacob    private boolean hasParameterTypes(MethodSymbol method, List<Type> paramTypes) {
67855371Smjacob        if (paramTypes == null)
67955371Smjacob            return true;
68055371Smjacob
681155228Smjacob        if (method.params().size() != paramTypes.size())
68255371Smjacob            return false;
68355371Smjacob
68455371Smjacob        List<Type> methodParamTypes = types.erasureRecursive(method.asType()).getParameterTypes();
68555371Smjacob
68655371Smjacob        return (Type.isErroneous(paramTypes))
68755371Smjacob            ? fuzzyMatch(paramTypes, methodParamTypes)
688155228Smjacob            : types.isSameTypes(paramTypes, methodParamTypes);
68984242Smjacob    }
69084242Smjacob
69184242Smjacob    boolean fuzzyMatch(List<Type> paramTypes, List<Type> methodParamTypes) {
69284242Smjacob        List<Type> l1 = paramTypes;
69384242Smjacob        List<Type> l2 = methodParamTypes;
69484242Smjacob        while (l1.nonEmpty()) {
69584242Smjacob            if (!fuzzyMatch(l1.head, l2.head))
69684242Smjacob                return false;
69784242Smjacob            l1 = l1.tail;
69884242Smjacob            l2 = l2.tail;
69984242Smjacob        }
70055371Smjacob        return true;
70175200Smjacob    }
70275200Smjacob
70355371Smjacob    boolean fuzzyMatch(Type paramType, Type methodParamType) {
70455371Smjacob        Boolean b = fuzzyMatcher.visit(paramType, methodParamType);
70555371Smjacob        return (b == Boolean.TRUE);
70675200Smjacob    }
70755371Smjacob
70855371Smjacob    TypeRelation fuzzyMatcher = new TypeRelation() {
70955371Smjacob        @Override
71055371Smjacob        public Boolean visitType(Type t, Type s) {
71155371Smjacob            if (t == s)
71255371Smjacob                return true;
71375200Smjacob
71455371Smjacob            if (s.isPartial())
71555371Smjacob                return visit(s, t);
71669557Sdwmalone
71755371Smjacob            switch (t.getTag()) {
71855371Smjacob            case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT:
71955371Smjacob            case DOUBLE: case BOOLEAN: case VOID: case BOT: case NONE:
72055371Smjacob                return t.hasTag(s.getTag());
72155371Smjacob            default:
72255371Smjacob                throw new AssertionError("fuzzyMatcher " + t.getTag());
72355371Smjacob            }
72455371Smjacob        }
72555371Smjacob
72655371Smjacob        @Override
72775200Smjacob        public Boolean visitArrayType(ArrayType t, Type s) {
72855371Smjacob            if (t == s)
72955371Smjacob                return true;
73055371Smjacob
73155371Smjacob            if (s.isPartial())
73255371Smjacob                return visit(s, t);
73375200Smjacob
73475200Smjacob            return s.hasTag(ARRAY)
73575200Smjacob                && visit(t.elemtype, types.elemtype(s));
73675200Smjacob        }
73755371Smjacob
73855371Smjacob        @Override
73955371Smjacob        public Boolean visitClassType(ClassType t, Type s) {
74055371Smjacob            if (t == s)
74155371Smjacob                return true;
74255371Smjacob
74355371Smjacob            if (s.isPartial())
74455371Smjacob                return visit(s, t);
74555371Smjacob
746155228Smjacob            return t.tsym == s.tsym;
74755371Smjacob        }
74855371Smjacob
74975200Smjacob        @Override
75055371Smjacob        public Boolean visitErrorType(ErrorType t, Type s) {
75155371Smjacob            return s.hasTag(CLASS)
75255371Smjacob                    && t.tsym.name == ((ClassType) s).tsym.name;
75355371Smjacob        }
75455371Smjacob    };
755125597Smjacob
75675200Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
75755371Smjacob    public TypeMirror getTypeMirror(TreePath path) {
75855371Smjacob        Tree t = path.getLeaf();
75975200Smjacob        Type ty = ((JCTree)t).type;
76075200Smjacob        return ty == null ? null : ty.stripMetadataIfNeeded();
76155371Smjacob    }
76255371Smjacob
76355371Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
76455371Smjacob    public JavacScope getScope(TreePath path) {
76575200Smjacob        return JavacScope.create(getAttrContext(path));
76655371Smjacob    }
76755371Smjacob
76855371Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
76955371Smjacob    public String getDocComment(TreePath path) {
77055371Smjacob        CompilationUnitTree t = path.getCompilationUnit();
77155371Smjacob        Tree leaf = path.getLeaf();
77255371Smjacob        if (t instanceof JCTree.JCCompilationUnit && leaf instanceof JCTree) {
77355371Smjacob            JCCompilationUnit cu = (JCCompilationUnit) t;
77455371Smjacob            if (cu.docComments != null) {
77555371Smjacob                return cu.docComments.getCommentText((JCTree) leaf);
77655371Smjacob            }
77755371Smjacob        }
77855371Smjacob        return null;
77977365Smjacob    }
780125597Smjacob
78177365Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
782125597Smjacob    public DocCommentTree getDocCommentTree(TreePath path) {
78355371Smjacob        CompilationUnitTree t = path.getCompilationUnit();
78455371Smjacob        Tree leaf = path.getLeaf();
78555371Smjacob        if (t instanceof JCTree.JCCompilationUnit && leaf instanceof JCTree) {
78655371Smjacob            JCCompilationUnit cu = (JCCompilationUnit) t;
787155704Smjacob            if (cu.docComments != null) {
788125549Smjacob                return cu.docComments.getCommentTree((JCTree) leaf);
78955371Smjacob            }
79055371Smjacob        }
79155371Smjacob        return null;
792125597Smjacob    }
793125597Smjacob
794125597Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
795125597Smjacob    public DocCommentTree getDocCommentTree(Element e) {
796125597Smjacob        TreePath path = getPath(e);
797125597Smjacob        if (path == null) {
798125597Smjacob            return null;
79955371Smjacob        }
80055371Smjacob        return getDocCommentTree(path);
80155371Smjacob    }
802125597Smjacob
803125597Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
804125597Smjacob    public DocCommentTree getDocCommentTree(Element e, String relativeFileName) throws IOException {
80565140Smjacob        PackageElement pkg = elements.getPackageOf(e);
806125597Smjacob        FileObject fileForInput = fileManager.getFileForInput(StandardLocation.SOURCE_PATH,
80772347Smjacob                pkg.getQualifiedName().toString(), relativeFileName);
80872347Smjacob
80965140Smjacob        if (fileForInput == null) {
810125597Smjacob            throw new FileNotFoundException(relativeFileName);
81165140Smjacob        }
81283028Smjacob        return getDocCommentTree(fileForInput);
81365140Smjacob    }
81475200Smjacob
81575200Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
81665140Smjacob    public boolean isAccessible(Scope scope, TypeElement type) {
81775200Smjacob        if (scope instanceof JavacScope && type instanceof ClassSymbol) {
81865140Smjacob            Env<AttrContext> env = ((JavacScope) scope).env;
819125597Smjacob            return resolve.isAccessible(env, (ClassSymbol)type, true);
82065140Smjacob        } else
82165140Smjacob            return false;
822125549Smjacob    }
823125549Smjacob
824125549Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
825125549Smjacob    public boolean isAccessible(Scope scope, Element member, DeclaredType type) {
826125549Smjacob        if (scope instanceof JavacScope
82765140Smjacob                && member instanceof Symbol
82872347Smjacob                && type instanceof com.sun.tools.javac.code.Type) {
82965140Smjacob            Env<AttrContext> env = ((JavacScope) scope).env;
830125597Smjacob            return resolve.isAccessible(env, (com.sun.tools.javac.code.Type)type, (Symbol)member, true);
83165140Smjacob        } else
832125549Smjacob            return false;
83383028Smjacob    }
83483028Smjacob
83583028Smjacob    private Env<AttrContext> getAttrContext(TreePath path) {
83683028Smjacob        if (!(path.getLeaf() instanceof JCTree))  // implicit null-check
83783028Smjacob            throw new IllegalArgumentException();
83883028Smjacob
83983028Smjacob        // if we're being invoked from a Tree API client via parse/enter/analyze,
840125597Smjacob        // we need to make sure all the classes have been entered;
84172347Smjacob        // if we're being invoked from JSR 199 or JSR 269, then the classes
84283028Smjacob        // will already have been entered.
84383028Smjacob        if (javacTaskImpl != null) {
84483028Smjacob            javacTaskImpl.enter(null);
84583028Smjacob        }
84683028Smjacob
84783028Smjacob        JCCompilationUnit unit = (JCCompilationUnit) path.getCompilationUnit();
84883028Smjacob        Copier copier = createCopier(treeMaker.forToplevel(unit));
849125549Smjacob
850125597Smjacob        Env<AttrContext> env = null;
85165140Smjacob        JCMethodDecl method = null;
85265140Smjacob        JCVariableDecl field = null;
85365140Smjacob
85483028Smjacob        List<Tree> l = List.nil();
85583028Smjacob        TreePath p = path;
85683028Smjacob        while (p != null) {
85783028Smjacob            l = l.prepend(p.getLeaf());
85883028Smjacob            p = p.getParentPath();
859125597Smjacob        }
86055371Smjacob
86182689Smjacob        for ( ; l.nonEmpty(); l = l.tail) {
86282689Smjacob            Tree tree = l.head;
86382689Smjacob            switch (tree.getKind()) {
86455371Smjacob                case COMPILATION_UNIT:
865125549Smjacob//                    System.err.println("COMP: " + ((JCCompilationUnit)tree).sourcefile);
866125549Smjacob                    env = enter.getTopLevelEnv((JCCompilationUnit)tree);
86755371Smjacob                    break;
86855371Smjacob                case ANNOTATION_TYPE:
86983028Smjacob                case CLASS:
87083028Smjacob                case ENUM:
87183028Smjacob                case INTERFACE:
87283028Smjacob//                    System.err.println("CLASS: " + ((JCClassDecl)tree).sym.getSimpleName());
87355371Smjacob                    env = enter.getClassEnv(((JCClassDecl)tree).sym);
87482689Smjacob                    break;
87582689Smjacob                case METHOD:
87675200Smjacob//                    System.err.println("METHOD: " + ((JCMethodDecl)tree).sym.getSimpleName());
87755371Smjacob                    method = (JCMethodDecl)tree;
878125597Smjacob                    env = memberEnter.getMethodEnv(method, env);
87955371Smjacob                    break;
880125597Smjacob                case VARIABLE:
88155371Smjacob//                    System.err.println("FIELD: " + ((JCVariableDecl)tree).sym.getSimpleName());
88255371Smjacob                    field = (JCVariableDecl)tree;
88355371Smjacob                    break;
88455371Smjacob                case BLOCK: {
88555371Smjacob//                    System.err.println("BLOCK: ");
88655371Smjacob                    if (method != null) {
88755371Smjacob                        try {
888125597Smjacob                            Assert.check(method.body == tree);
88955371Smjacob                            method.body = copier.copy((JCBlock)tree, (JCTree) path.getLeaf());
89055371Smjacob                            env = attribStatToTree(method.body, env, copier.leafCopy);
89155371Smjacob                        } finally {
89283028Smjacob                            method.body = (JCBlock) tree;
89355371Smjacob                        }
894125597Smjacob                    } else {
89582689Smjacob                        JCBlock body = copier.copy((JCBlock)tree, (JCTree) path.getLeaf());
896125597Smjacob                        env = attribStatToTree(body, env, copier.leafCopy);
89755371Smjacob                    }
89882689Smjacob                    return env;
89955371Smjacob                }
900125597Smjacob                default:
90155371Smjacob//                    System.err.println("DEFAULT: " + tree.getKind());
90282689Smjacob                    if (field != null && field.getInitializer() == tree) {
90383028Smjacob                        env = memberEnter.getInitEnv(field, env);
90482689Smjacob                        JCExpression expr = copier.copy((JCExpression)tree, (JCTree) path.getLeaf());
90582689Smjacob                        env = attribExprToTree(expr, env, copier.leafCopy);
90682689Smjacob                        return env;
90782689Smjacob                    }
90882689Smjacob            }
90982689Smjacob        }
91082689Smjacob        return (field != null) ? memberEnter.getInitEnv(field, env) : env;
91182689Smjacob    }
912125549Smjacob
91382689Smjacob    private Env<AttrContext> attribStatToTree(JCTree stat, Env<AttrContext>env, JCTree tree) {
91482689Smjacob        JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
91582689Smjacob        try {
91682689Smjacob            return attr.attribStatToTree(stat, env, tree);
91782689Smjacob        } finally {
91883028Smjacob            log.useSource(prev);
91983028Smjacob        }
92082689Smjacob    }
92155371Smjacob
922125597Smjacob    private Env<AttrContext> attribExprToTree(JCExpression expr, Env<AttrContext>env, JCTree tree) {
92355371Smjacob        JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
92483028Smjacob        try {
92582689Smjacob            return attr.attribExprToTree(expr, env, tree);
92682689Smjacob        } finally {
927125549Smjacob            log.useSource(prev);
92882689Smjacob        }
92982689Smjacob    }
930125597Smjacob
93182689Smjacob    static JavaFileObject asJavaFileObject(FileObject fileObject) {
93282689Smjacob        JavaFileObject jfo = null;
93382689Smjacob
93482689Smjacob        if (fileObject instanceof JavaFileObject) {
935125597Smjacob            jfo = (JavaFileObject) fileObject;
93682689Smjacob            checkHtmlKind(fileObject, Kind.HTML);
93783028Smjacob            return jfo;
93882689Smjacob        }
93982689Smjacob
94082689Smjacob        checkHtmlKind(fileObject);
94182689Smjacob        jfo = new HtmlFileObject(fileObject);
94282689Smjacob        return jfo;
94383028Smjacob    }
944125597Smjacob
94555371Smjacob    private static void checkHtmlKind(FileObject fileObject) {
94655371Smjacob        checkHtmlKind(fileObject, BaseFileManager.getKind(fileObject.getName()));
947125597Smjacob    }
948125597Smjacob
949125597Smjacob    private static void checkHtmlKind(FileObject fileObject, JavaFileObject.Kind kind) {
950125597Smjacob        if (kind != JavaFileObject.Kind.HTML) {
951125597Smjacob            throw new IllegalArgumentException("HTML file expected:" + fileObject.getName());
952125597Smjacob        }
953125597Smjacob    }
954125597Smjacob
955125597Smjacob    private static class HtmlFileObject extends ForwardingFileObject<FileObject>
956125597Smjacob            implements JavaFileObject {
957125597Smjacob
958125597Smjacob        public HtmlFileObject(FileObject fileObject) {
959125597Smjacob            super(fileObject);
960125597Smjacob        }
961125597Smjacob
96255371Smjacob        @Override @DefinedBy(Api.COMPILER)
96355371Smjacob        public Kind getKind() {
96475200Smjacob            return BaseFileManager.getKind(fileObject.getName());
96555371Smjacob        }
966125597Smjacob
967125597Smjacob        @Override @DefinedBy(Api.COMPILER)
96855371Smjacob        public boolean isNameCompatible(String simpleName, Kind kind) {
96955371Smjacob            return false;
97075200Smjacob        }
97155371Smjacob
97255371Smjacob        @Override @DefinedBy(Api.COMPILER)
973125597Smjacob        public NestingKind getNestingKind() {
97455371Smjacob            return null;
97555371Smjacob        }
97655371Smjacob
97755371Smjacob        @Override @DefinedBy(Api.COMPILER)
97877365Smjacob        public Modifier getAccessLevel() {
97977365Smjacob            return null;
98077365Smjacob        }
98177365Smjacob    }
98277365Smjacob
98377365Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
98477365Smjacob    public DocCommentTree getDocCommentTree(FileObject fileObject) {
98577365Smjacob        JavaFileObject jfo = asJavaFileObject(fileObject);
98677365Smjacob        DiagnosticSource diagSource = new DiagnosticSource(jfo, log);
98777365Smjacob
98877365Smjacob        final Comment comment = new Comment() {
98977365Smjacob            int offset = 0;
99077365Smjacob            @Override
99177365Smjacob            public String getText() {
992125597Smjacob                try {
993125597Smjacob                    CharSequence rawDoc = fileObject.getCharContent(true);
994125597Smjacob                    Pattern bodyPat =
995125597Smjacob                            Pattern.compile("(?is).*?<body\\b[^>]*>(.*)</body\\b.*");
99655371Smjacob                    Matcher m = bodyPat.matcher(rawDoc);
99755371Smjacob                    if (m.matches()) {
99877365Smjacob                        offset = m.end(1);
99955371Smjacob                        return m.group(1);
100077365Smjacob                    } else {
100177365Smjacob                        // Assume doclint will do the right thing.
100277365Smjacob                        return "";
100377365Smjacob                    }
100477365Smjacob                } catch (IOException ignore) {
100577365Smjacob                    // do nothing
100677365Smjacob                }
100777365Smjacob                return "";
100877365Smjacob            }
100977365Smjacob
101077365Smjacob            @Override
1011125597Smjacob            public int getSourcePos(int index) {
1012125597Smjacob                return offset + index;
1013125597Smjacob            }
1014125597Smjacob
101555371Smjacob            @Override
1016125597Smjacob            public CommentStyle getStyle() {
1017125597Smjacob                throw new UnsupportedOperationException();
1018125597Smjacob            }
1019125597Smjacob
1020125597Smjacob            @Override
1021125597Smjacob            public boolean isDeprecated() {
1022125597Smjacob                throw new UnsupportedOperationException();
1023125597Smjacob            }
102477365Smjacob        };
1025125597Smjacob
1026125597Smjacob        return new DocCommentParser(parser, diagSource, comment).parse();
1027125597Smjacob    }
1028125597Smjacob
1029125597Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
1030155704Smjacob    public DocTreePath getDocTreePath(FileObject fileObject) {
1031125597Smjacob        JavaFileObject jfo = asJavaFileObject(fileObject);
1032125597Smjacob        DocCommentTree docCommentTree = getDocCommentTree(jfo);
1033125597Smjacob        return new DocTreePath(makeTreePath(jfo, docCommentTree), docCommentTree);
103455371Smjacob    }
1035125597Smjacob
1036125597Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
1037125597Smjacob    public void setBreakIterator(BreakIterator breakiterator) {
1038125597Smjacob        this.breakIterator = breakiterator;
1039125597Smjacob    }
104055371Smjacob
1041125597Smjacob    /**
1042125597Smjacob     * Makes a copy of a tree, noting the value resulting from copying a particular leaf.
1043125597Smjacob     **/
1044125597Smjacob    protected static class Copier extends TreeCopier<JCTree> {
1045125597Smjacob        JCTree leafCopy = null;
1046125597Smjacob
1047125597Smjacob        protected Copier(TreeMaker M) {
1048125597Smjacob            super(M);
1049125597Smjacob        }
1050125597Smjacob
1051125597Smjacob        @Override
1052125597Smjacob        public <T extends JCTree> T copy(T t, JCTree leaf) {
1053125597Smjacob            T t2 = super.copy(t, leaf);
1054125597Smjacob            if (t == leaf)
105582689Smjacob                leafCopy = t2;
1056125597Smjacob            return t2;
105755371Smjacob        }
1058125597Smjacob    }
1059125597Smjacob
106055371Smjacob    protected Copier createCopier(TreeMaker maker) {
1061125597Smjacob        return new Copier(maker);
106255371Smjacob    }
1063125597Smjacob
1064125597Smjacob    /**
1065125597Smjacob     * Returns the original type from the ErrorType object.
1066125597Smjacob     * @param errorType The errorType for which we want to get the original type.
1067125597Smjacob     * @return TypeMirror corresponding to the original type, replaced by the ErrorType.
106855371Smjacob     *         noType (type.tag == NONE) is returned if there is no original type.
1069125597Smjacob     */
1070125597Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
1071125597Smjacob    public TypeMirror getOriginalType(javax.lang.model.type.ErrorType errorType) {
1072125597Smjacob        if (errorType instanceof com.sun.tools.javac.code.Type.ErrorType) {
1073125597Smjacob            return ((com.sun.tools.javac.code.Type.ErrorType)errorType).getOriginalType();
1074125597Smjacob        }
1075125597Smjacob
1076125597Smjacob        return com.sun.tools.javac.code.Type.noType;
1077125597Smjacob    }
107855371Smjacob
1079125597Smjacob    /**
1080125597Smjacob     * Prints a message of the specified kind at the location of the
1081125597Smjacob     * tree within the provided compilation unit
1082125597Smjacob     *
1083125597Smjacob     * @param kind the kind of message
1084125597Smjacob     * @param msg  the message, or an empty string if none
1085125597Smjacob     * @param t    the tree to use as a position hint
1086125597Smjacob     * @param root the compilation unit that contains tree
1087125597Smjacob     */
1088125597Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
1089125597Smjacob    public void printMessage(Diagnostic.Kind kind, CharSequence msg,
1090125597Smjacob            com.sun.source.tree.Tree t,
1091125597Smjacob            com.sun.source.tree.CompilationUnitTree root) {
109255371Smjacob        printMessage(kind, msg, ((JCTree) t).pos(), root);
1093125597Smjacob    }
1094125597Smjacob
109555371Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
1096125597Smjacob    public void printMessage(Diagnostic.Kind kind, CharSequence msg,
1097125597Smjacob            com.sun.source.doctree.DocTree t,
1098125597Smjacob            com.sun.source.doctree.DocCommentTree c,
1099125597Smjacob            com.sun.source.tree.CompilationUnitTree root) {
1100125597Smjacob        printMessage(kind, msg, ((DCTree) t).pos((DCDocComment) c), root);
1101125597Smjacob    }
1102125597Smjacob
1103125597Smjacob    private void printMessage(Diagnostic.Kind kind, CharSequence msg,
1104125597Smjacob            JCDiagnostic.DiagnosticPosition pos,
1105125597Smjacob            com.sun.source.tree.CompilationUnitTree root) {
1106125597Smjacob        JavaFileObject oldSource = null;
1107125597Smjacob        JavaFileObject newSource = null;
1108125597Smjacob
1109125597Smjacob        newSource = root.getSourceFile();
1110125597Smjacob        if (newSource == null) {
1111125597Smjacob            pos = null;
1112125597Smjacob        } else {
1113125597Smjacob            oldSource = log.useSource(newSource);
1114125597Smjacob        }
1115125597Smjacob
1116125597Smjacob        try {
1117125597Smjacob            switch (kind) {
111855371Smjacob            case ERROR:
111955371Smjacob                log.error(DiagnosticFlag.MULTIPLE, pos, "proc.messager", msg.toString());
1120125597Smjacob                break;
112155371Smjacob
112255371Smjacob            case WARNING:
112355371Smjacob                log.warning(pos, "proc.messager", msg.toString());
112455371Smjacob                break;
112555371Smjacob
112655371Smjacob            case MANDATORY_WARNING:
1127125549Smjacob                log.mandatoryWarning(pos, "proc.messager", msg.toString());
112855371Smjacob                break;
112955371Smjacob
1130125549Smjacob            default:
113155371Smjacob                log.note(pos, "proc.messager", msg.toString());
1132125549Smjacob            }
113355371Smjacob        } finally {
113455371Smjacob            if (oldSource != null)
1135125549Smjacob                log.useSource(oldSource);
113655371Smjacob        }
113755371Smjacob    }
1138125549Smjacob
1139125549Smjacob    @Override @DefinedBy(Api.COMPILER_TREE)
1140125549Smjacob    public TypeMirror getLub(CatchTree tree) {
1141125549Smjacob        JCCatch ct = (JCCatch) tree;
1142125549Smjacob        JCVariableDecl v = ct.param;
1143125549Smjacob        if (v.type != null && v.type.getKind() == TypeKind.UNION) {
1144125549Smjacob            UnionClassType ut = (UnionClassType) v.type;
1145125549Smjacob            return ut.getLub();
1146125549Smjacob        } else {
114755371Smjacob            return v.type;
1148125549Smjacob        }
114955371Smjacob    }
115055371Smjacob
115175200Smjacob    /**
115255371Smjacob     * Register a file object, such as for a package.html, that provides
1153125549Smjacob     * doc comments for a package.
1154125549Smjacob     * @param psym the PackageSymbol representing the package.
115555371Smjacob     * @param jfo  the JavaFileObject for the given package.
115655371Smjacob     */
115755371Smjacob    public void putJavaFileObject(PackageSymbol psym, JavaFileObject jfo) {
115855371Smjacob        javaFileObjectToPackageMap.putIfAbsent(jfo, psym);
1159125549Smjacob    }
116055371Smjacob
116155371Smjacob    private TreePath makeTreePath(final JavaFileObject jfo, DocCommentTree dcTree) {
1162125549Smjacob        JCCompilationUnit jcCompilationUnit = new JCCompilationUnit(List.nil()) {
116355371Smjacob            public int getPos() {
116455371Smjacob                return Position.FIRSTPOS;
1165125549Smjacob            }
1166125549Smjacob
116755371Smjacob            public JavaFileObject getSourcefile() {
116855371Smjacob                return jfo;
116955371Smjacob            }
117055371Smjacob
117155371Smjacob            @Override @DefinedBy(Api.COMPILER_TREE)
117255371Smjacob            public Position.LineMap getLineMap() {
117355371Smjacob                try {
117455371Smjacob                    CharSequence content = jfo.getCharContent(true);
117555371Smjacob                    String s = content.toString();
117655371Smjacob                    return Position.makeLineMap(s.toCharArray(), s.length(), true);
117755371Smjacob                } catch (IOException ignore) {}
117855371Smjacob                return null;
117955371Smjacob            }
118055371Smjacob        };
118155371Smjacob
118255371Smjacob        PackageSymbol psym = javaFileObjectToPackageMap.getOrDefault(jfo, syms.unnamedPackage);
118355371Smjacob
118455371Smjacob        jcCompilationUnit.docComments = new DocCommentTable() {
118555371Smjacob            @Override
118655371Smjacob            public boolean hasComment(JCTree tree) {
118755371Smjacob                return false;
118855371Smjacob            }
118955371Smjacob
1190125549Smjacob            @Override
119155371Smjacob            public Comment getComment(JCTree tree) {
1192125549Smjacob                throw new UnsupportedOperationException();
119355371Smjacob            }
119455371Smjacob
1195125549Smjacob            @Override
1196125549Smjacob            public String getCommentText(JCTree tree) {
1197125549Smjacob                throw new UnsupportedOperationException();
119855371Smjacob            }
119955371Smjacob
120055371Smjacob            @Override
120155371Smjacob            public DCDocComment getCommentTree(JCTree tree) {
120255371Smjacob                return (DCDocComment)dcTree;
120355371Smjacob            }
120456007Smjacob
1205155704Smjacob            @Override
1206155704Smjacob            public void putComment(JCTree tree, Comment c) {
1207155704Smjacob                throw new UnsupportedOperationException();
120855371Smjacob            }
120963385Smjacob
121087635Smjacob        };
121155387Smjacob        jcCompilationUnit.lineMap = jcCompilationUnit.getLineMap();
121255387Smjacob        jcCompilationUnit.namedImportScope = new NamedImportScope(psym, jcCompilationUnit.toplevelScope);
121355371Smjacob        jcCompilationUnit.packge = psym;
121455371Smjacob        jcCompilationUnit.starImportScope = null;
121587635Smjacob        jcCompilationUnit.sourcefile = jfo;
121655371Smjacob        jcCompilationUnit.starImportScope = new StarImportScope(psym);
121755371Smjacob        jcCompilationUnit.toplevelScope = WriteableScope.create(psym);
121855371Smjacob
121955371Smjacob        return new TreePath(jcCompilationUnit);
122055371Smjacob    }
122155371Smjacob}
122284242Smjacob