blob: 7cdae1fd915c31be7d1303efc5ba83fbef809a61 [file] [log] [blame]
/*******************************************************************************
* 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();
}
}