blob: 1f0163426cecc76478f65956713c2f9493c7d253 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.core.dom;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.jdt.internal.core.NameLookup;
import org.eclipse.jdt.internal.core.SearchableEnvironment;
/**
* Internal implementation of package bindings.
*/
@SuppressWarnings("rawtypes")
class PackageBinding implements IPackageBinding {
private static final String[] NO_NAME_COMPONENTS = CharOperation.NO_STRINGS;
private static final String UNNAMED = Util.EMPTY_STRING;
private static final char PACKAGE_NAME_SEPARATOR = '.';
private org.eclipse.jdt.internal.compiler.lookup.PackageBinding binding;
private String name;
private BindingResolver resolver;
private String[] components;
PackageBinding(org.eclipse.jdt.internal.compiler.lookup.PackageBinding binding, BindingResolver resolver) {
this.binding = binding;
this.resolver = resolver;
}
@Override
public IAnnotationBinding[] getAnnotations() {
try {
INameEnvironment nameEnvironment = this.binding.environment.nameEnvironment;
if (!(nameEnvironment instanceof SearchableEnvironment))
return AnnotationBinding.NoAnnotations;
NameLookup nameLookup = ((SearchableEnvironment) nameEnvironment).nameLookup;
if (nameLookup == null)
return AnnotationBinding.NoAnnotations;
final String pkgName = getName();
IPackageFragment[] pkgs = nameLookup.findPackageFragments(pkgName, false/*exact match*/);
if (pkgs == null)
return AnnotationBinding.NoAnnotations;
for (int i = 0, len = pkgs.length; i < len; i++) {
int fragType = pkgs[i].getKind();
switch(fragType) {
case IPackageFragmentRoot.K_SOURCE:
String unitName = "package-info.java"; //$NON-NLS-1$
ICompilationUnit unit = pkgs[i].getCompilationUnit(unitName);
if (unit != null && unit.exists()) {
ASTParser p = ASTParser.newParser(AST.JLS3_INTERNAL);
p.setSource(unit);
p.setResolveBindings(true);
p.setUnitName(unitName);
p.setFocalPosition(0);
p.setKind(ASTParser.K_COMPILATION_UNIT);
CompilationUnit domUnit = (CompilationUnit) p.createAST(null);
PackageDeclaration pkgDecl = domUnit.getPackage();
if (pkgDecl != null) {
List annos = pkgDecl.annotations();
if (annos == null || annos.isEmpty())
return AnnotationBinding.NoAnnotations;
IAnnotationBinding[] result = new IAnnotationBinding[annos.size()];
int index=0;
for (Iterator it = annos.iterator(); it.hasNext(); index++) {
result[index] = ((Annotation) it.next()).resolveAnnotationBinding();
// not resolving bindings
if (result[index] == null)
return AnnotationBinding.NoAnnotations;
}
return result;
}
}
break;
case IPackageFragmentRoot.K_BINARY:
NameEnvironmentAnswer answer =
nameEnvironment.findType(TypeConstants.PACKAGE_INFO_NAME, this.binding.compoundName);
if (answer != null && answer.isBinaryType()) {
IBinaryType type = answer.getBinaryType();
char[][][] missingTypeNames = type.getMissingTypeNames();
IBinaryAnnotation[] binaryAnnotations = type.getAnnotations();
org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] binaryInstances =
BinaryTypeBinding.createAnnotations(binaryAnnotations, this.binding.environment, missingTypeNames);
org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] allInstances =
org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding.addStandardAnnotations(binaryInstances, type.getTagBits(), this.binding.environment);
int total = allInstances.length;
IAnnotationBinding[] domInstances = new AnnotationBinding[total];
for (int a = 0; a < total; a++) {
final IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(allInstances[a]);
if (annotationInstance == null) {// not resolving binding
return AnnotationBinding.NoAnnotations;
}
domInstances[a] = annotationInstance;
}
return domInstances;
}
}
}
} catch(JavaModelException e) {
return AnnotationBinding.NoAnnotations;
}
return AnnotationBinding.NoAnnotations;
}
@Override
public IModuleBinding getModule() {
ModuleBinding moduleBinding = this.binding.enclosingModule;
return moduleBinding != null ? this.resolver.getModuleBinding(moduleBinding) : null;
}
@Override
public String getName() {
if (this.name == null) {
computeNameAndComponents();
}
return this.name;
}
@Override
public boolean isUnnamed() {
return getName().equals(UNNAMED);
}
@Override
public String[] getNameComponents() {
if (this.components == null) {
computeNameAndComponents();
}
return this.components;
}
@Override
public int getKind() {
return IBinding.PACKAGE;
}
@Override
public int getModifiers() {
return Modifier.NONE;
}
@Override
public boolean isDeprecated() {
return false;
}
/**
* @see IBinding#isRecovered()
*/
@Override
public boolean isRecovered() {
return false;
}
/**
* @see IBinding#isSynthetic()
*/
@Override
public boolean isSynthetic() {
return false;
}
@Override
public IJavaElement getJavaElement() {
INameEnvironment nameEnvironment = this.binding.environment.nameEnvironment; // a package binding always has a LooupEnvironment set
if (!(nameEnvironment instanceof SearchableEnvironment)) return null;
// this is not true in standalone DOM/AST
NameLookup nameLookup = ((SearchableEnvironment) nameEnvironment).nameLookup;
if (nameLookup == null) return null;
IJavaElement[] pkgs = nameLookup.findPackageFragments(getName(), false/*exact match*/);
if (pkgs == null) return null;
if (pkgs.length == 0) {
// add additional tracing as this should not happen
org.eclipse.jdt.internal.core.util.Util.log(
new Status(
IStatus.WARNING,
JavaCore.PLUGIN_ID,
"Searching for package " + getName() + " returns an empty array")); //$NON-NLS-1$ //$NON-NLS-2$
return null;
}
return pkgs[0];
}
@Override
public String getKey() {
return new String(this.binding.computeUniqueKey());
}
@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 PackageBinding)) {
return false;
}
org.eclipse.jdt.internal.compiler.lookup.PackageBinding packageBinding2 = ((PackageBinding) other).binding;
return CharOperation.equals(this.binding.compoundName, packageBinding2.compoundName);
}
private void computeNameAndComponents() {
char[][] compoundName = this.binding.compoundName;
if (compoundName == CharOperation.NO_CHAR_CHAR || compoundName == null) {
this.name = UNNAMED;
this.components = NO_NAME_COMPONENTS;
} else {
int length = compoundName.length;
this.components = new String[length];
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < length - 1; i++) {
this.components[i] = new String(compoundName[i]);
buffer.append(compoundName[i]).append(PACKAGE_NAME_SEPARATOR);
}
this.components[length - 1] = new String(compoundName[length - 1]);
buffer.append(compoundName[length - 1]);
this.name = buffer.toString();
}
}
org.eclipse.jdt.internal.compiler.lookup.PackageBinding getCompilerBinding() {
return this.binding;
}
/*
* For debugging purpose only.
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return this.binding.toString();
}
}