1 /*
2 * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.javac.model;
27
28 import java.util.Arrays;
29 import java.util.Collections;
30 import java.util.HashMap;
31 import java.util.HashSet;
32 import java.util.LinkedHashSet;
33 import java.util.Map;
34 import java.util.Optional;
35 import java.util.Set;
36 import java.util.stream.Collectors;
37
38 import javax.lang.model.AnnotatedConstruct;
39 import javax.lang.model.SourceVersion;
40 import javax.lang.model.element.*;
41 import javax.lang.model.type.DeclaredType;
42 import javax.lang.model.util.Elements;
43 import javax.tools.JavaFileObject;
44 import static javax.lang.model.util.ElementFilter.methodsIn;
45
46 import com.sun.source.util.JavacTask;
47 import com.sun.tools.javac.api.JavacTaskImpl;
48 import com.sun.tools.javac.code.*;
49 import com.sun.tools.javac.code.Attribute.Compound;
50 import com.sun.tools.javac.code.Directive.ExportsDirective;
51 import com.sun.tools.javac.code.Directive.ExportsFlag;
52 import com.sun.tools.javac.code.Directive.OpensDirective;
53 import com.sun.tools.javac.code.Directive.OpensFlag;
54 import com.sun.tools.javac.code.Directive.RequiresDirective;
55 import com.sun.tools.javac.code.Directive.RequiresFlag;
56 import com.sun.tools.javac.code.Scope.WriteableScope;
57 import com.sun.tools.javac.code.Source.Feature;
58 import com.sun.tools.javac.code.Symbol.*;
59 import com.sun.tools.javac.comp.AttrContext;
60 import com.sun.tools.javac.comp.Enter;
61 import com.sun.tools.javac.comp.Env;
62 import com.sun.tools.javac.main.JavaCompiler;
63 import com.sun.tools.javac.processing.PrintingProcessor;
64 import com.sun.tools.javac.tree.JCTree;
65 import com.sun.tools.javac.tree.JCTree.*;
66 import com.sun.tools.javac.tree.TreeInfo;
67 import com.sun.tools.javac.tree.TreeScanner;
68 import com.sun.tools.javac.util.*;
69 import com.sun.tools.javac.util.DefinedBy.Api;
70 import com.sun.tools.javac.util.Name;
71 import static com.sun.tools.javac.code.Kinds.Kind.*;
72 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
73 import static com.sun.tools.javac.code.TypeTag.CLASS;
74 import com.sun.tools.javac.comp.Attr;
75 import com.sun.tools.javac.comp.Modules;
76 import com.sun.tools.javac.comp.Resolve;
77 import com.sun.tools.javac.comp.Resolve.RecoveryLoadClass;
78 import com.sun.tools.javac.resources.CompilerProperties.Notes;
79 import static com.sun.tools.javac.tree.JCTree.Tag.*;
80
81 /**
82 * Utility methods for operating on program elements.
83 *
84 * <p><b>This is NOT part of any supported API.
85 * If you write code that depends on this, you do so at your own
86 * risk. This code and its internal interfaces are subject to change
87 * or deletion without notice.</b></p>
88 */
89 public class JavacElements implements Elements {
90
91 private final JavaCompiler javaCompiler;
92 private final Symtab syms;
93 private final Modules modules;
94 private final Names names;
95 private final Types types;
96 private final Enter enter;
97 private final Attr attr;
98 private final Resolve resolve;
99 private final JavacTaskImpl javacTaskImpl;
100 private final Log log;
101 private final boolean allowModules;
102
103 public static JavacElements instance(Context context) {
104 JavacElements instance = context.get(JavacElements.class);
105 if (instance == null)
106 instance = new JavacElements(context);
107 return instance;
108 }
109
110 @SuppressWarnings("this-escape")
111 protected JavacElements(Context context) {
112 context.put(JavacElements.class, this);
113 javaCompiler = JavaCompiler.instance(context);
114 syms = Symtab.instance(context);
115 modules = Modules.instance(context);
116 names = Names.instance(context);
117 types = Types.instance(context);
118 enter = Enter.instance(context);
119 attr = Attr.instance(context);
120 resolve = Resolve.instance(context);
121 JavacTask t = context.get(JavacTask.class);
122 javacTaskImpl = t instanceof JavacTaskImpl taskImpl ? taskImpl : null;
123 log = Log.instance(context);
124 Source source = Source.instance(context);
125 allowModules = Feature.MODULES.allowedInSource(source);
126 }
127
128 @Override @DefinedBy(Api.LANGUAGE_MODEL)
129 public Set<? extends ModuleElement> getAllModuleElements() {
130 if (allowModules)
131 return Collections.unmodifiableSet(modules.allModules());
132 else
133 return Collections.emptySet();
134 }
135
136 @Override @DefinedBy(Api.LANGUAGE_MODEL)
137 public ModuleSymbol getModuleElement(CharSequence name) {
138 ensureEntered("getModuleElement");
139 if (modules.getDefaultModule() == syms.noModule)
140 return null;
141 String strName = name.toString();
142 if (strName.equals(""))
143 return syms.unnamedModule;
776 case PCK -> {
777 PackageSymbol psym = (PackageSymbol) sym;
778 if (psym.package_info == null) {
779 yield null;
780 }
781 yield psym.package_info.classfile;
782 }
783
784 case MDL -> {
785 ModuleSymbol msym = (ModuleSymbol) sym;
786 if (msym.module_info == null) {
787 yield null;
788 }
789 yield msym.module_info.classfile;
790 }
791 case TYP -> ((ClassSymbol) sym).classfile;
792 default -> sym.enclClass().classfile;
793 };
794 }
795
796 /**
797 * Returns the tree node and compilation unit corresponding to this
798 * element, or null if they can't be found.
799 */
800 private Pair<JCTree, JCCompilationUnit> getTreeAndTopLevel(Element e) {
801 Symbol sym = cast(Symbol.class, e);
802 if (sym.kind == PCK) {
803 TypeSymbol pkgInfo = ((PackageSymbol) sym).package_info;
804 if (pkgInfo != null) {
805 pkgInfo.complete();
806 }
807 }
808 Env<AttrContext> enterEnv = getEnterEnv(sym);
809 if (enterEnv == null)
810 return null;
811 JCTree tree = TreeInfo.declarationFor(sym, enterEnv.tree);
812 if (tree == null || enterEnv.toplevel == null)
813 return null;
814 return new Pair<>(tree, enterEnv.toplevel);
815 }
|
1 /*
2 * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.javac.model;
27
28 import java.lang.reflect.Method;
29 import java.util.Arrays;
30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.LinkedHashSet;
34 import java.util.Map;
35 import java.util.Optional;
36 import java.util.Set;
37 import java.util.stream.Collectors;
38
39 import javax.lang.model.AnnotatedConstruct;
40 import javax.lang.model.SourceVersion;
41 import javax.lang.model.element.*;
42 import javax.lang.model.type.DeclaredType;
43 import javax.lang.model.util.Elements;
44 import javax.tools.JavaFileObject;
45 import static javax.lang.model.util.ElementFilter.methodsIn;
46
47 import com.sun.source.tree.Tree;
48 import com.sun.source.util.JavacTask;
49 import com.sun.tools.javac.api.JavacScope;
50 import com.sun.tools.javac.api.JavacTaskImpl;
51 import com.sun.tools.javac.api.JavacTrees;
52 import com.sun.tools.javac.code.*;
53 import com.sun.tools.javac.code.Attribute.Compound;
54 import com.sun.tools.javac.code.Directive.ExportsDirective;
55 import com.sun.tools.javac.code.Directive.ExportsFlag;
56 import com.sun.tools.javac.code.Directive.OpensDirective;
57 import com.sun.tools.javac.code.Directive.OpensFlag;
58 import com.sun.tools.javac.code.Directive.RequiresDirective;
59 import com.sun.tools.javac.code.Directive.RequiresFlag;
60 import com.sun.tools.javac.code.Scope.WriteableScope;
61 import com.sun.tools.javac.code.Source.Feature;
62 import com.sun.tools.javac.code.Symbol.*;
63 import com.sun.tools.javac.comp.Attr;
64 import com.sun.tools.javac.comp.AttrContext;
65 import com.sun.tools.javac.comp.Enter;
66 import com.sun.tools.javac.comp.Env;
67 import com.sun.tools.javac.comp.ReflectMethods;
68 import com.sun.tools.javac.main.JavaCompiler;
69 import com.sun.tools.javac.processing.PrintingProcessor;
70 import com.sun.tools.javac.tree.JCTree;
71 import com.sun.tools.javac.tree.JCTree.*;
72 import com.sun.tools.javac.tree.TreeInfo;
73 import com.sun.tools.javac.tree.TreeMaker;
74 import com.sun.tools.javac.tree.TreeScanner;
75 import com.sun.tools.javac.util.*;
76 import com.sun.tools.javac.util.DefinedBy.Api;
77 import com.sun.tools.javac.util.Name;
78 import static com.sun.tools.javac.code.Kinds.Kind.*;
79 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
80 import static com.sun.tools.javac.code.TypeTag.CLASS;
81
82 import com.sun.tools.javac.comp.Modules;
83 import com.sun.tools.javac.comp.Resolve;
84 import com.sun.tools.javac.resources.CompilerProperties.Notes;
85 import jdk.internal.java.lang.reflect.code.op.CoreOp;
86
87 import static com.sun.tools.javac.tree.JCTree.Tag.*;
88
89 /**
90 * Utility methods for operating on program elements.
91 *
92 * <p><b>This is NOT part of any supported API.
93 * If you write code that depends on this, you do so at your own
94 * risk. This code and its internal interfaces are subject to change
95 * or deletion without notice.</b></p>
96 */
97 public class JavacElements implements Elements {
98
99 private final JavaCompiler javaCompiler;
100 private final Symtab syms;
101 private final Modules modules;
102 private final Names names;
103 private final Types types;
104 private final Enter enter;
105 private final JavacTrees javacTrees;
106 private final Attr attr;
107 private final Resolve resolve;
108 private final ReflectMethods reflectMethods;
109 private final JavacTaskImpl javacTaskImpl;
110 private final Log log;
111 private final TreeMaker make;
112 private final boolean allowModules;
113
114 public static JavacElements instance(Context context) {
115 JavacElements instance = context.get(JavacElements.class);
116 if (instance == null)
117 instance = new JavacElements(context);
118 return instance;
119 }
120
121 @SuppressWarnings("this-escape")
122 protected JavacElements(Context context) {
123 context.put(JavacElements.class, this);
124 javaCompiler = JavaCompiler.instance(context);
125 syms = Symtab.instance(context);
126 modules = Modules.instance(context);
127 names = Names.instance(context);
128 types = Types.instance(context);
129 enter = Enter.instance(context);
130 attr = Attr.instance(context);
131 resolve = Resolve.instance(context);
132 javacTrees = JavacTrees.instance(context);
133 reflectMethods = ReflectMethods.instance(context);
134 JavacTask t = context.get(JavacTask.class);
135 javacTaskImpl = t instanceof JavacTaskImpl taskImpl ? taskImpl : null;
136 log = Log.instance(context);
137 make = TreeMaker.instance(context);
138 Source source = Source.instance(context);
139 allowModules = Feature.MODULES.allowedInSource(source);
140 }
141
142 @Override @DefinedBy(Api.LANGUAGE_MODEL)
143 public Set<? extends ModuleElement> getAllModuleElements() {
144 if (allowModules)
145 return Collections.unmodifiableSet(modules.allModules());
146 else
147 return Collections.emptySet();
148 }
149
150 @Override @DefinedBy(Api.LANGUAGE_MODEL)
151 public ModuleSymbol getModuleElement(CharSequence name) {
152 ensureEntered("getModuleElement");
153 if (modules.getDefaultModule() == syms.noModule)
154 return null;
155 String strName = name.toString();
156 if (strName.equals(""))
157 return syms.unnamedModule;
790 case PCK -> {
791 PackageSymbol psym = (PackageSymbol) sym;
792 if (psym.package_info == null) {
793 yield null;
794 }
795 yield psym.package_info.classfile;
796 }
797
798 case MDL -> {
799 ModuleSymbol msym = (ModuleSymbol) sym;
800 if (msym.module_info == null) {
801 yield null;
802 }
803 yield msym.module_info.classfile;
804 }
805 case TYP -> ((ClassSymbol) sym).classfile;
806 default -> sym.enclClass().classfile;
807 };
808 }
809
810 @Override @DefinedBy(Api.LANGUAGE_MODEL)
811 public Optional<Object> getBody(ExecutableElement e) {
812 if (e.getModifiers().contains(Modifier.ABSTRACT) ||
813 e.getModifiers().contains(Modifier.NATIVE)) {
814 return Optional.empty();
815 }
816
817 CoreOp.FuncOp funcOp;
818 try {
819 JCMethodDecl methodTree = (JCMethodDecl)getTree(e);
820 JavacScope scope = javacTrees.getScope(javacTrees.getPath(e));
821 ClassSymbol enclosingClass = (ClassSymbol) scope.getEnclosingClass();
822 funcOp = attr.runWithAttributedMethod(scope.getEnv(), methodTree,
823 attribBlock -> reflectMethods.getMethodBody(enclosingClass, methodTree, attribBlock, make));
824 } catch (RuntimeException ex) { // ReflectMethods.UnsupportedASTException
825 // some other error occurred when attempting to attribute the method
826 // @@@ better report of error
827 ex.printStackTrace();
828 return Optional.empty();
829 }
830
831 // Reparse using API in java.base
832 try {
833 String opString = funcOp.toText();
834 Class<?> opParserClass = Class.forName("java.lang.reflect.code.parser.OpParser");
835 Method fromStringMethod = opParserClass.getDeclaredMethod("fromStringOfFuncOp", String.class);
836 return Optional.of(fromStringMethod.invoke(null, opString));
837 } catch (ReflectiveOperationException ex) {
838 throw new RuntimeException(ex);
839 }
840 }
841
842 /**
843 * Returns the tree node and compilation unit corresponding to this
844 * element, or null if they can't be found.
845 */
846 private Pair<JCTree, JCCompilationUnit> getTreeAndTopLevel(Element e) {
847 Symbol sym = cast(Symbol.class, e);
848 if (sym.kind == PCK) {
849 TypeSymbol pkgInfo = ((PackageSymbol) sym).package_info;
850 if (pkgInfo != null) {
851 pkgInfo.complete();
852 }
853 }
854 Env<AttrContext> enterEnv = getEnterEnv(sym);
855 if (enterEnv == null)
856 return null;
857 JCTree tree = TreeInfo.declarationFor(sym, enterEnv.tree);
858 if (tree == null || enterEnv.toplevel == null)
859 return null;
860 return new Pair<>(tree, enterEnv.toplevel);
861 }
|