1 | /******************************************************************************* |
---|---|
2 | * Copyright (c) 2017 IBM Corporation and others. |
3 | * |
4 | * This program and the accompanying materials |
5 | * are made available under the terms of the Eclipse Public License 2.0 |
6 | * which accompanies this distribution, and is available at |
7 | * https://www.eclipse.org/legal/epl-2.0/ |
8 | * |
9 | * SPDX-License-Identifier: EPL-2.0 |
10 | * |
11 | * Contributors: |
12 | * IBM Corporation - initial API and implementation |
13 | * |
14 | *******************************************************************************/ |
15 | package org.eclipse.jdt.core.dom; |
16 | |
17 | import java.util.Arrays; |
18 | import org.eclipse.jdt.core.IJavaElement; |
19 | import org.eclipse.jdt.core.compiler.CharOperation; |
20 | import org.eclipse.jdt.internal.compiler.env.INameEnvironment; |
21 | import org.eclipse.jdt.internal.compiler.util.Util; |
22 | import org.eclipse.jdt.internal.core.NameLookup; |
23 | import org.eclipse.jdt.internal.core.NameLookup.Answer; |
24 | import org.eclipse.jdt.internal.core.SearchableEnvironment; |
25 | |
26 | /** |
27 | * Internal implementation of module bindings. |
28 | * @since 3.14 |
29 | */ |
30 | class ModuleBinding implements IModuleBinding { |
31 | |
32 | protected static final ITypeBinding[] NO_TYPE_BINDINGS = new ITypeBinding[0]; |
33 | private String name = null; |
34 | private volatile String key; |
35 | private boolean isOpen = false; |
36 | |
37 | private org.eclipse.jdt.internal.compiler.lookup.ModuleBinding binding; |
38 | protected BindingResolver resolver; |
39 | |
40 | private IAnnotationBinding[] annotations; |
41 | private IModuleBinding[] requiredModules; |
42 | private IPackageBinding[] exports; // cached |
43 | private IPackageBinding[] opens; // cached |
44 | private ITypeBinding[] uses; // cached |
45 | private ITypeBinding[] services; // cached |
46 | |
47 | ModuleBinding(BindingResolver resolver, org.eclipse.jdt.internal.compiler.lookup.ModuleBinding binding) { |
48 | this.resolver = resolver; |
49 | this.binding = binding; |
50 | this.isOpen = binding.isOpen(); |
51 | } |
52 | |
53 | @Override |
54 | public IAnnotationBinding[] getAnnotations() { |
55 | if (this.annotations == null) { |
56 | this.annotations = resolveAnnotationBindings(this.binding.getAnnotations()); |
57 | } |
58 | return this.annotations; |
59 | } |
60 | |
61 | private IAnnotationBinding[] resolveAnnotationBindings(org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations) { |
62 | int length = internalAnnotations == null ? 0 : internalAnnotations.length; |
63 | if (length != 0) { |
64 | IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length]; |
65 | int convertedAnnotationCount = 0; |
66 | for (int i = 0; i < length; i++) { |
67 | org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i]; |
68 | if (internalAnnotation == null) |
69 | break; |
70 | IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation); |
71 | if (annotationInstance == null) |
72 | continue; |
73 | tempAnnotations[convertedAnnotationCount++] = annotationInstance; |
74 | } |
75 | if (convertedAnnotationCount != length) { |
76 | if (convertedAnnotationCount == 0) { |
77 | return this.annotations = AnnotationBinding.NoAnnotations; |
78 | } |
79 | System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount); |
80 | } |
81 | return tempAnnotations; |
82 | } |
83 | return AnnotationBinding.NoAnnotations; |
84 | } |
85 | |
86 | @Override |
87 | public String getName() { |
88 | if (this.name == null) { |
89 | char[] tmp = this.binding.moduleName; |
90 | return tmp != null && tmp.length != 0 ? new String(tmp) : Util.EMPTY_STRING; |
91 | } |
92 | return this.name; |
93 | } |
94 | |
95 | @Override |
96 | public int getModifiers() { |
97 | // TODO Auto-generated method stub |
98 | return 0; |
99 | } |
100 | |
101 | @Override |
102 | public boolean isDeprecated() { |
103 | return false; |
104 | } |
105 | |
106 | @Override |
107 | public boolean isRecovered() { |
108 | return false; |
109 | } |
110 | |
111 | @Override |
112 | public boolean isSynthetic() { |
113 | // TODO Auto-generated method stub |
114 | // TODO Java 9 no reference seen in jvms draft - only in sotm |
115 | // check on version change and after compiler ast implements isSynthetic return this.binding.isSynthetic(); |
116 | |
117 | return false; |
118 | } |
119 | |
120 | @Override |
121 | public IJavaElement getJavaElement() { |
122 | INameEnvironment nameEnvironment = this.binding.environment.nameEnvironment; |
123 | if (!(nameEnvironment instanceof SearchableEnvironment)) return null; |
124 | NameLookup nameLookup = ((SearchableEnvironment) nameEnvironment).nameLookup; |
125 | if (nameLookup == null) return null; |
126 | Answer answer = nameLookup.findModule(this.getName().toCharArray()); |
127 | if (answer == null) return null; |
128 | return answer.module; |
129 | } |
130 | |
131 | @Override |
132 | public String getKey() { |
133 | if (this.key == null) { |
134 | char[] k = this.binding.computeUniqueKey(); |
135 | this.key = k == null || k == CharOperation.NO_CHAR ? Util.EMPTY_STRING : new String(k); |
136 | } |
137 | return this.key; |
138 | } |
139 | |
140 | @Override |
141 | public boolean isEqualTo(IBinding other) { |
142 | if (other == this) // identical binding - equal (key or no key) |
143 | return true; |
144 | if (other == null) // other binding missing |
145 | return false; |
146 | |
147 | if (!(other instanceof ModuleBinding)) |
148 | return false; |
149 | |
150 | org.eclipse.jdt.internal.compiler.lookup.ModuleBinding otherBinding = ((ModuleBinding) other).binding; |
151 | return BindingComparator.isEqual(this.binding, otherBinding); |
152 | } |
153 | |
154 | @Override |
155 | public boolean isOpen() { |
156 | return this.isOpen; |
157 | } |
158 | @Override |
159 | public IModuleBinding[] getRequiredModules() { |
160 | if (this.requiredModules != null) |
161 | return this.requiredModules; |
162 | |
163 | org.eclipse.jdt.internal.compiler.lookup.ModuleBinding[] reqs = this.binding.getRequires(); |
164 | IModuleBinding[] result = new IModuleBinding[reqs != null ? reqs.length : 0]; |
165 | for (int i = 0, l = result.length; i < l; ++i) { |
166 | org.eclipse.jdt.internal.compiler.lookup.ModuleBinding req = reqs[i]; |
167 | result[i] = req != null ? this.resolver.getModuleBinding(req) : null; |
168 | } |
169 | return this.requiredModules = result; |
170 | } |
171 | |
172 | @Override |
173 | public IPackageBinding[] getExportedPackages() { |
174 | if (this.exports == null) { |
175 | org.eclipse.jdt.internal.compiler.lookup.PackageBinding[] compilerExports = this.binding.getExports(); |
176 | this.exports = Arrays.stream(compilerExports) |
177 | .map(e -> this.resolver.getPackageBinding(e)) |
178 | .toArray(IPackageBinding[]::new); |
179 | } |
180 | return this.exports; |
181 | } |
182 | |
183 | @Override |
184 | public String[] getExportedTo(IPackageBinding packageBinding) { |
185 | return this.binding.getExportRestrictions(((PackageBinding) packageBinding).getCompilerBinding()); |
186 | } |
187 | |
188 | @Override |
189 | public IPackageBinding[] getOpenedPackages() { |
190 | if (this.opens == null) { |
191 | org.eclipse.jdt.internal.compiler.lookup.PackageBinding[] compilerOpens = this.binding.getOpens(); |
192 | this.opens = Arrays.stream(compilerOpens) |
193 | .map(o -> this.resolver.getPackageBinding(o)) |
194 | .toArray(IPackageBinding[]::new); |
195 | } |
196 | return this.opens; |
197 | } |
198 | |
199 | @Override |
200 | public String[] getOpenedTo(IPackageBinding packageBinding) { |
201 | return this.binding.getOpenRestrictions(((PackageBinding) packageBinding).getCompilerBinding()); |
202 | } |
203 | |
204 | /* |
205 | * helper method |
206 | */ |
207 | private ITypeBinding[] getTypes(org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] types) { |
208 | int length = types == null ? 0 : types.length; |
209 | TypeBinding[] result = new TypeBinding[length]; |
210 | for (int i = 0; i < length; ++i) { |
211 | result[i] = (TypeBinding) this.resolver.getTypeBinding(types[i]); |
212 | } |
213 | return result; |
214 | } |
215 | |
216 | @Override |
217 | public ITypeBinding[] getUses() { |
218 | if (this.uses == null) |
219 | this.uses = getTypes(this.binding.getUses()); |
220 | return this.uses; |
221 | } |
222 | |
223 | @Override |
224 | public ITypeBinding[] getServices() { |
225 | if (this.services == null) |
226 | this.services = getTypes(this.binding.getServices()); |
227 | return this.services; |
228 | } |
229 | @Override |
230 | public ITypeBinding[] getImplementations(ITypeBinding service) { |
231 | return getTypes(this.binding.getImplementations(((TypeBinding) service).binding)); |
232 | } |
233 | /** |
234 | * For debugging purpose only. |
235 | * @see java.lang.Object#toString() |
236 | */ |
237 | @Override |
238 | public String toString() { |
239 | return this.binding.toString(); |
240 | } |
241 | } |
242 |
Members