| /******************************************************************************* |
| * Copyright (c) 2017 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * |
| *******************************************************************************/ |
| package org.eclipse.jdt.core.dom; |
| |
| import java.util.Arrays; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.compiler.CharOperation; |
| import org.eclipse.jdt.internal.compiler.env.INameEnvironment; |
| import org.eclipse.jdt.internal.compiler.util.Util; |
| import org.eclipse.jdt.internal.core.NameLookup; |
| import org.eclipse.jdt.internal.core.NameLookup.Answer; |
| import org.eclipse.jdt.internal.core.SearchableEnvironment; |
| |
| /** |
| * Internal implementation of module bindings. |
| * @since 3.14 |
| */ |
| class ModuleBinding implements IModuleBinding { |
| |
| protected static final ITypeBinding[] NO_TYPE_BINDINGS = new ITypeBinding[0]; |
| private String name = null; |
| private volatile String key; |
| private boolean isOpen = false; |
| |
| private org.eclipse.jdt.internal.compiler.lookup.ModuleBinding binding; |
| protected BindingResolver resolver; |
| |
| private IAnnotationBinding[] annotations; |
| private IModuleBinding[] requiredModules; |
| private IPackageBinding[] exports; // cached |
| private IPackageBinding[] opens; // cached |
| private ITypeBinding[] uses; // cached |
| private ITypeBinding[] services; // cached |
| |
| ModuleBinding(BindingResolver resolver, org.eclipse.jdt.internal.compiler.lookup.ModuleBinding binding) { |
| this.resolver = resolver; |
| this.binding = binding; |
| this.isOpen = binding.isOpen(); |
| } |
| |
| @Override |
| public IAnnotationBinding[] getAnnotations() { |
| if (this.annotations == null) { |
| this.annotations = resolveAnnotationBindings(this.binding.getAnnotations()); |
| } |
| return this.annotations; |
| } |
| |
| private IAnnotationBinding[] resolveAnnotationBindings(org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations) { |
| int length = internalAnnotations == null ? 0 : internalAnnotations.length; |
| if (length != 0) { |
| IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length]; |
| int convertedAnnotationCount = 0; |
| for (int i = 0; i < length; i++) { |
| org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i]; |
| if (internalAnnotation == null) |
| break; |
| IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation); |
| if (annotationInstance == null) |
| continue; |
| tempAnnotations[convertedAnnotationCount++] = annotationInstance; |
| } |
| if (convertedAnnotationCount != length) { |
| if (convertedAnnotationCount == 0) { |
| return this.annotations = AnnotationBinding.NoAnnotations; |
| } |
| System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount); |
| } |
| return tempAnnotations; |
| } |
| return AnnotationBinding.NoAnnotations; |
| } |
| |
| @Override |
| public String getName() { |
| if (this.name == null) { |
| char[] tmp = this.binding.moduleName; |
| return tmp != null && tmp.length != 0 ? new String(tmp) : Util.EMPTY_STRING; |
| } |
| return this.name; |
| } |
| |
| @Override |
| public int getModifiers() { |
| // TODO Auto-generated method stub |
| return 0; |
| } |
| |
| @Override |
| public boolean isDeprecated() { |
| return false; |
| } |
| |
| @Override |
| public boolean isRecovered() { |
| return false; |
| } |
| |
| @Override |
| public boolean isSynthetic() { |
| // TODO Auto-generated method stub |
| // TODO Java 9 no reference seen in jvms draft - only in sotm |
| // check on version change and after compiler ast implements isSynthetic return this.binding.isSynthetic(); |
| |
| return false; |
| } |
| |
| @Override |
| public IJavaElement getJavaElement() { |
| INameEnvironment nameEnvironment = this.binding.environment.nameEnvironment; |
| if (!(nameEnvironment instanceof SearchableEnvironment)) return null; |
| NameLookup nameLookup = ((SearchableEnvironment) nameEnvironment).nameLookup; |
| if (nameLookup == null) return null; |
| Answer answer = nameLookup.findModule(this.getName().toCharArray()); |
| if (answer == null) return null; |
| return answer.module; |
| } |
| |
| @Override |
| public String getKey() { |
| if (this.key == null) { |
| char[] k = this.binding.computeUniqueKey(); |
| this.key = k == null || k == CharOperation.NO_CHAR ? Util.EMPTY_STRING : new String(k); |
| } |
| return this.key; |
| } |
| |
| @Override |
| public boolean isEqualTo(IBinding other) { |
| if (other == this) // identical binding - equal (key or no key) |
| return true; |
| if (other == null) // other binding missing |
| return false; |
| |
| if (!(other instanceof ModuleBinding)) |
| return false; |
| |
| org.eclipse.jdt.internal.compiler.lookup.ModuleBinding otherBinding = ((ModuleBinding) other).binding; |
| return BindingComparator.isEqual(this.binding, otherBinding); |
| } |
| |
| @Override |
| public boolean isOpen() { |
| return this.isOpen; |
| } |
| @Override |
| public IModuleBinding[] getRequiredModules() { |
| if (this.requiredModules != null) |
| return this.requiredModules; |
| |
| org.eclipse.jdt.internal.compiler.lookup.ModuleBinding[] reqs = this.binding.getRequires(); |
| IModuleBinding[] result = new IModuleBinding[reqs != null ? reqs.length : 0]; |
| for (int i = 0, l = result.length; i < l; ++i) { |
| org.eclipse.jdt.internal.compiler.lookup.ModuleBinding req = reqs[i]; |
| result[i] = req != null ? this.resolver.getModuleBinding(req) : null; |
| } |
| return this.requiredModules = result; |
| } |
| |
| @Override |
| public IPackageBinding[] getExportedPackages() { |
| if (this.exports == null) { |
| org.eclipse.jdt.internal.compiler.lookup.PackageBinding[] compilerExports = this.binding.getExports(); |
| this.exports = Arrays.stream(compilerExports) |
| .map(e -> this.resolver.getPackageBinding(e)) |
| .toArray(IPackageBinding[]::new); |
| } |
| return this.exports; |
| } |
| |
| @Override |
| public String[] getExportedTo(IPackageBinding packageBinding) { |
| return this.binding.getExportRestrictions(((PackageBinding) packageBinding).getCompilerBinding()); |
| } |
| |
| @Override |
| public IPackageBinding[] getOpenedPackages() { |
| if (this.opens == null) { |
| org.eclipse.jdt.internal.compiler.lookup.PackageBinding[] compilerOpens = this.binding.getOpens(); |
| this.opens = Arrays.stream(compilerOpens) |
| .map(o -> this.resolver.getPackageBinding(o)) |
| .toArray(IPackageBinding[]::new); |
| } |
| return this.opens; |
| } |
| |
| @Override |
| public String[] getOpenedTo(IPackageBinding packageBinding) { |
| return this.binding.getOpenRestrictions(((PackageBinding) packageBinding).getCompilerBinding()); |
| } |
| |
| /* |
| * helper method |
| */ |
| private ITypeBinding[] getTypes(org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] types) { |
| int length = types == null ? 0 : types.length; |
| TypeBinding[] result = new TypeBinding[length]; |
| for (int i = 0; i < length; ++i) { |
| result[i] = (TypeBinding) this.resolver.getTypeBinding(types[i]); |
| } |
| return result; |
| } |
| |
| @Override |
| public ITypeBinding[] getUses() { |
| if (this.uses == null) |
| this.uses = getTypes(this.binding.getUses()); |
| return this.uses; |
| } |
| |
| @Override |
| public ITypeBinding[] getServices() { |
| if (this.services == null) |
| this.services = getTypes(this.binding.getServices()); |
| return this.services; |
| } |
| @Override |
| public ITypeBinding[] getImplementations(ITypeBinding service) { |
| return getTypes(this.binding.getImplementations(((TypeBinding) service).binding)); |
| } |
| /** |
| * For debugging purpose only. |
| * @see java.lang.Object#toString() |
| */ |
| public String toString() { |
| return this.binding.toString(); |
| } |
| } |