| 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