Extract descriptor.loader.java module from frontend.java

Will be used in runtime to load reflected classes
This commit is contained in:
Alexander Udalov
2013-08-21 16:12:09 +04:00
parent 4fa35047b0
commit 2b9225fdd4
107 changed files with 97 additions and 37 deletions
@@ -1,23 +0,0 @@
package org.jetbrains.jet.cli.jvm.compiler;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public final class ClassPath implements Iterable<VirtualFile> {
@NotNull
private final List<VirtualFile> roots = new ArrayList<VirtualFile>();
@Override
public Iterator<VirtualFile> iterator() {
return roots.iterator();
}
public void add(@NotNull VirtualFile root) {
roots.add(root);
}
}
@@ -1,28 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java;
public final class AbiVersionUtil {
public static final int INVALID_VERSION = -1;
public static boolean isAbiVersionCompatible(int abiVersion) {
return abiVersion == JvmAbi.VERSION;
}
private AbiVersionUtil() {
}
}
@@ -1,61 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import java.util.HashMap;
import java.util.Map;
public class AsmTypeConstants {
private static final Map<Class<?>, Type> TYPES_MAP = new HashMap<Class<?>, Type>();
public static final Type OBJECT_TYPE = getType(Object.class);
public static final Type JAVA_STRING_TYPE = getType(String.class);
public static final Type JAVA_THROWABLE_TYPE = getType(Throwable.class);
public static final Type JAVA_ARRAY_GENERIC_TYPE = getType(Object[].class);
public static final Type JET_NOTHING_TYPE = Type.getObjectType("jet/Nothing");
public static final Type JET_UNIT_TYPE = Type.getObjectType("jet/Unit");
public static final Type JET_FUNCTION0_TYPE = Type.getObjectType("jet/Function0");
public static final Type JET_FUNCTION1_TYPE = Type.getObjectType("jet/Function1");
public static final Type JET_ITERATOR_TYPE = Type.getObjectType("jet/Iterator");
public static final Type JET_INT_RANGE_TYPE = Type.getObjectType("jet/IntRange");
public static final Type JET_SHARED_VAR_TYPE = Type.getObjectType("jet/runtime/SharedVar$Object");
public static final Type JET_SHARED_INT_TYPE = Type.getObjectType("jet/runtime/SharedVar$Int");
public static final Type JET_SHARED_DOUBLE_TYPE = Type.getObjectType("jet/runtime/SharedVar$Double");
public static final Type JET_SHARED_FLOAT_TYPE = Type.getObjectType("jet/runtime/SharedVar$Float");
public static final Type JET_SHARED_BYTE_TYPE = Type.getObjectType("jet/runtime/SharedVar$Byte");
public static final Type JET_SHARED_SHORT_TYPE = Type.getObjectType("jet/runtime/SharedVar$Short");
public static final Type JET_SHARED_CHAR_TYPE = Type.getObjectType("jet/runtime/SharedVar$Char");
public static final Type JET_SHARED_LONG_TYPE = Type.getObjectType("jet/runtime/SharedVar$Long");
public static final Type JET_SHARED_BOOLEAN_TYPE = Type.getObjectType("jet/runtime/SharedVar$Boolean");
public static Type getType(@NotNull Class<?> javaClass) {
Type type = TYPES_MAP.get(javaClass);
if (type == null) {
type = Type.getType(javaClass);
TYPES_MAP.put(javaClass, type);
}
return type;
}
private AsmTypeConstants() {
}
}
@@ -1,36 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
public enum DescriptorSearchRule {
INCLUDE_KOTLIN_SOURCES {
@Override
public <T extends DeclarationDescriptor> T processFoundInKotlin(T foundDescriptor) {
return foundDescriptor;
}
},
IGNORE_KOTLIN_SOURCES {
@Override
public <T extends DeclarationDescriptor> T processFoundInKotlin(T foundDescriptor) {
return null;
}
};
public abstract <T extends DeclarationDescriptor> T processFoundInKotlin(T foundDescriptor);
}
@@ -1,59 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java;
import com.google.common.collect.ImmutableList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.DefaultModuleConfiguration;
import org.jetbrains.jet.lang.ModuleConfiguration;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.ImportPath;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import javax.inject.Inject;
import java.util.List;
public class JavaBridgeConfiguration implements ModuleConfiguration {
public static final List<ImportPath> DEFAULT_JAVA_IMPORTS = ImmutableList.of(new ImportPath("java.lang.*"));
public static final List<ImportPath> ALL_JAVA_IMPORTS = ImmutableList.<ImportPath>builder()
.addAll(DEFAULT_JAVA_IMPORTS)
.addAll(DefaultModuleConfiguration.DEFAULT_JET_IMPORTS)
.build();
private JavaDescriptorResolver javaDescriptorResolver;
@Inject
public void setJavaDescriptorResolver(@NotNull JavaDescriptorResolver javaDescriptorResolver) {
this.javaDescriptorResolver = javaDescriptorResolver;
}
@Override
public void extendNamespaceScope(
@NotNull BindingTrace trace,
@NotNull NamespaceDescriptor namespaceDescriptor,
@NotNull WritableScope namespaceMemberScope
) {
JetScope javaPackageScope = javaDescriptorResolver.getJavaPackageScope(namespaceDescriptor);
if (javaPackageScope != null) {
namespaceMemberScope.importScope(javaPackageScope);
}
DefaultModuleConfiguration.INSTANCE.extendNamespaceScope(trace, namespaceDescriptor, namespaceMemberScope);
}
}
@@ -1,32 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.java.structure.JavaPackage;
import org.jetbrains.jet.lang.resolve.name.FqName;
public interface JavaClassFinder {
// TODO: scope
@Nullable
JavaClass findClass(@NotNull FqName fqName);
@Nullable
JavaPackage findPackage(@NotNull FqName fqName);
}
@@ -1,69 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.java.resolver.JavaClassResolver;
import org.jetbrains.jet.lang.resolve.java.resolver.JavaNamespaceResolver;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolver;
import javax.inject.Inject;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.IGNORE_KOTLIN_SOURCES;
public class JavaDescriptorResolver implements DependencyClassByQualifiedNameResolver {
public static final Name JAVA_ROOT = Name.special("<java_root>");
private JavaClassResolver classResolver;
private JavaNamespaceResolver namespaceResolver;
@Inject
public void setClassResolver(JavaClassResolver classResolver) {
this.classResolver = classResolver;
}
@Inject
public void setNamespaceResolver(JavaNamespaceResolver namespaceResolver) {
this.namespaceResolver = namespaceResolver;
}
@Nullable
public ClassDescriptor resolveClass(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule) {
return classResolver.resolveClass(qualifiedName, searchRule);
}
@Override
public ClassDescriptor resolveClass(@NotNull FqName qualifiedName) {
return classResolver.resolveClass(qualifiedName, IGNORE_KOTLIN_SOURCES);
}
@Nullable
public NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule) {
return namespaceResolver.resolveNamespace(qualifiedName, searchRule);
}
@Nullable
public JetScope getJavaPackageScope(@NotNull NamespaceDescriptor namespaceDescriptor) {
return namespaceResolver.getJavaPackageScopeForExistingNamespaceDescriptor(namespaceDescriptor);
}
}
@@ -1,165 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorParent;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
public class JavaVisibilities {
private JavaVisibilities() {
}
public static final Visibility PACKAGE_VISIBILITY = new Visibility("package", false) {
@Override
protected boolean isVisible(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
return isInSameNamespace(what, from);
}
@Override
protected Integer compareTo(@NotNull Visibility visibility) {
if (this == visibility) return 0;
if (visibility == Visibilities.PRIVATE) return 1;
return -1;
}
@Override
public String toString() {
return "public/*package*/";
}
@NotNull
@Override
public Visibility normalize() {
return Visibilities.INTERNAL;
}
};
public static final Visibility PROTECTED_STATIC_VISIBILITY = new Visibility("protected_static", false) {
@Override
protected boolean isVisible(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
ClassDescriptor fromClass = DescriptorUtils.getParentOfType(from, ClassDescriptor.class, false);
if (fromClass == null) return false;
ClassDescriptor whatClass;
// protected static class
if (what instanceof ClassDescriptor) {
DeclarationDescriptor containingDeclaration = what.getContainingDeclaration();
assert containingDeclaration instanceof ClassDescriptor : "Only static nested classes can have protected_static visibility";
whatClass = (ClassDescriptor) containingDeclaration;
}
// protected static function or property
else {
DeclarationDescriptor whatDeclarationDescriptor = what.getContainingDeclaration();
assert whatDeclarationDescriptor instanceof NamespaceDescriptor : "Only static declarations can have protected_static visibility";
whatClass = getClassForCorrespondingJavaNamespace((NamespaceDescriptor) whatDeclarationDescriptor);
}
assert whatClass != null : "Couldn't find ClassDescriptor for protected static member " + what;
if (DescriptorUtils.isSubclass(fromClass, whatClass)) {
return true;
}
return isVisible(what, fromClass.getContainingDeclaration());
}
@Override
public String toString() {
return "protected/*protected static*/";
}
@NotNull
@Override
public Visibility normalize() {
return Visibilities.PROTECTED;
}
};
public static final Visibility PROTECTED_AND_PACKAGE = new Visibility("protected_and_package", false) {
@Override
protected boolean isVisible(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
if (isInSameNamespace(what, from)) {
return true;
}
ClassDescriptor whatClass = DescriptorUtils.getParentOfType(what, ClassDescriptor.class, false);
if (whatClass == null) return false;
ClassDescriptor fromClass = DescriptorUtils.getParentOfType(from, ClassDescriptor.class, false);
if (fromClass == null) return false;
if (DescriptorUtils.isSubclass(fromClass, whatClass)) {
return true;
}
return isVisible(what, fromClass.getContainingDeclaration());
}
@Override
protected Integer compareTo(@NotNull Visibility visibility) {
if (this == visibility) return 0;
if (visibility == Visibilities.INTERNAL) return null;
if (visibility == Visibilities.PRIVATE) return 1;
return -1;
}
@Override
public String toString() {
return "protected/*protected and package*/";
}
@NotNull
@Override
public Visibility normalize() {
return Visibilities.PROTECTED;
}
};
private static boolean isInSameNamespace(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second) {
NamespaceDescriptor whatPackage = DescriptorUtils.getParentOfType(first, NamespaceDescriptor.class, false);
NamespaceDescriptor fromPackage = DescriptorUtils.getParentOfType(second, NamespaceDescriptor.class, false);
return fromPackage != null && whatPackage != null && whatPackage.equals(fromPackage);
}
@Nullable
private static ClassDescriptor getClassForCorrespondingJavaNamespace(@NotNull NamespaceDescriptor correspondingNamespace) {
NamespaceDescriptorParent containingDeclaration = correspondingNamespace.getContainingDeclaration();
if (!(containingDeclaration instanceof NamespaceDescriptor)) {
return null;
}
NamespaceDescriptor namespaceDescriptor = (NamespaceDescriptor) containingDeclaration;
ClassifierDescriptor classDescriptor = namespaceDescriptor.getMemberScope().getClassifier(correspondingNamespace.getName());
if (classDescriptor != null && classDescriptor instanceof ClassDescriptor) {
return (ClassDescriptor) classDescriptor;
}
ClassDescriptor classDescriptorForOuterClass = getClassForCorrespondingJavaNamespace(namespaceDescriptor);
if (classDescriptorForOuterClass == null) {
return null;
}
ClassifierDescriptor innerClassDescriptor =
classDescriptorForOuterClass.getUnsubstitutedInnerClassesScope().getClassifier(correspondingNamespace.getName());
if (innerClassDescriptor instanceof ClassDescriptor) {
return (ClassDescriptor) innerClassDescriptor;
}
return null;
}
}
@@ -1,79 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
public final class JvmAbi {
/**
* This constant is used to identify binary format (class file) versions
* If you change class file metadata format and/or naming conventions, please increase this number
*/
public static final int VERSION = 7;
public static final String TRAIT_IMPL_CLASS_NAME = "$TImpl";
public static final String TRAIT_IMPL_SUFFIX = "$" + TRAIT_IMPL_CLASS_NAME;
public static final String DEFAULT_PARAMS_IMPL_SUFFIX = "$default";
public static final String GETTER_PREFIX = "get";
public static final String SETTER_PREFIX = "set";
public static final String CLASS_OBJECT_CLASS_NAME = "object";
public static final String CLASS_OBJECT_SUFFIX = "$" + CLASS_OBJECT_CLASS_NAME;
public static final String DELEGATED_PROPERTY_NAME_SUFFIX = "$delegate";
public static final String ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX = "$annotations";
public static final String ANNOTATED_PROPERTY_METHOD_SIGNATURE = "()V";
public static final String INSTANCE_FIELD = "instance$";
public static final String CLASS_OBJECT_FIELD = "object$";
public static final JvmClassName JET_OBJECT = JvmClassName.byFqNameWithoutInnerClasses("jet.JetObject");
public static boolean isClassObjectFqName(@NotNull FqName fqName) {
return fqName.lastSegmentIs(Name.identifier(CLASS_OBJECT_CLASS_NAME));
}
@NotNull
public static String getPropertyDelegateName(@NotNull Name name) {
return name.asString() + DELEGATED_PROPERTY_NAME_SUFFIX;
}
@NotNull
public static String getSyntheticMethodNameForAnnotatedProperty(@NotNull Name propertyName) {
return propertyName.asString() + ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX;
}
@NotNull
public static String getDefaultPropertyName(@NotNull Name propertyName, boolean isDelegated, boolean isExtensionProperty) {
if (isDelegated) {
return getPropertyDelegateName(propertyName);
}
String name = propertyName.asString();
if (isExtensionProperty) {
name += "$ext";
}
return name;
}
private JvmAbi() {
}
}
@@ -1,53 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java;
import jet.KotlinClass;
import jet.KotlinPackage;
import jet.runtime.typeinfo.KotlinSignature;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.rt.annotation.AssertInvisibleInResolver;
public final class JvmAnnotationNames {
public static final JvmClassName KOTLIN_CLASS = JvmClassName.byClass(KotlinClass.class);
public static final JvmClassName KOTLIN_PACKAGE = JvmClassName.byClass(KotlinPackage.class);
public static final String ABI_VERSION_FIELD_NAME = "abiVersion";
public static final String DATA_FIELD_NAME = "data";
@Deprecated
public static final JvmClassName OLD_JET_CLASS_ANNOTATION = JvmClassName.byFqNameWithoutInnerClasses("jet.runtime.typeinfo.JetClass");
@Deprecated
public static final JvmClassName OLD_JET_PACKAGE_CLASS_ANNOTATION = JvmClassName.byFqNameWithoutInnerClasses("jet.runtime.typeinfo.JetPackageClass");
public static final JvmClassName ASSERT_INVISIBLE_IN_RESOLVER = JvmClassName.byClass(AssertInvisibleInResolver.class);
public static final JvmClassName KOTLIN_SIGNATURE = JvmClassName.byClass(KotlinSignature.class);
public static final Name KOTLIN_SIGNATURE_VALUE_FIELD_NAME = Name.identifier("value");
public static final JvmClassName JETBRAINS_NOT_NULL_ANNOTATION = JvmClassName.byClass(NotNull.class);
public static final JvmClassName JETBRAINS_MUTABLE_ANNOTATION = JvmClassName.byFqNameWithoutInnerClasses("org.jetbrains.annotations.Mutable");
public static final JvmClassName JETBRAINS_READONLY_ANNOTATION = JvmClassName.byFqNameWithoutInnerClasses("org.jetbrains.annotations.ReadOnly");
private JvmAnnotationNames() {
}
}
@@ -1,237 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.name.FqName;
import java.util.ArrayList;
import java.util.List;
public class JvmClassName {
@NotNull
public static JvmClassName byInternalName(@NotNull String internalName) {
return new JvmClassName(internalName);
}
@NotNull
public static JvmClassName byType(@NotNull Type type) {
if (type.getSort() != Type.OBJECT) {
throw new IllegalArgumentException("Type is not convertible to " + JvmClassName.class.getSimpleName() + ": " + type);
}
return byInternalName(type.getInternalName());
}
/**
* WARNING: fq name cannot be uniquely mapped to JVM class name.
*/
@NotNull
public static JvmClassName byFqNameWithoutInnerClasses(@NotNull FqName fqName) {
JvmClassName r = new JvmClassName(fqNameToInternalName(fqName));
r.fqName = fqName;
return r;
}
@NotNull
public static JvmClassName byFqNameWithoutInnerClasses(@NotNull String fqName) {
return byFqNameWithoutInnerClasses(new FqName(fqName));
}
@NotNull
public static JvmClassName byClass(@NotNull Class<?> klass) {
return byFqNameWithoutInnerClasses(new FqName(klass.getCanonicalName()));
}
@NotNull
public static JvmClassName bySignatureName(@NotNull String signatureName) {
JvmClassName className = new JvmClassName(signatureNameToInternalName(signatureName));
className.signatureName = signatureName;
return className;
}
private static String encodeSpecialNames(String str) {
String encodedObjectNames = StringUtil.replace(str, JvmAbi.CLASS_OBJECT_CLASS_NAME, CLASS_OBJECT_REPLACE_GUARD);
return StringUtil.replace(encodedObjectNames, JvmAbi.TRAIT_IMPL_CLASS_NAME, TRAIT_IMPL_REPLACE_GUARD);
}
private static String decodeSpecialNames(String str) {
String decodedObjectNames = StringUtil.replace(str, CLASS_OBJECT_REPLACE_GUARD, JvmAbi.CLASS_OBJECT_CLASS_NAME);
return StringUtil.replace(decodedObjectNames, TRAIT_IMPL_REPLACE_GUARD, JvmAbi.TRAIT_IMPL_CLASS_NAME);
}
@NotNull
private static JvmClassName byFqNameAndInnerClassList(@NotNull FqName fqName, @NotNull List<String> innerClassList) {
String outerClassName = fqNameToInternalName(fqName);
StringBuilder sb = new StringBuilder(outerClassName);
for (String innerClassName : innerClassList) {
sb.append("$").append(innerClassName);
}
return new JvmClassName(sb.toString());
}
@NotNull
public static JvmClassName byClassDescriptor(@NotNull ClassifierDescriptor classDescriptor) {
DeclarationDescriptor descriptor = classDescriptor;
List<String> innerClassNames = new ArrayList<String>();
while (descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
innerClassNames.add(descriptor.getName().asString());
descriptor = descriptor.getContainingDeclaration();
assert descriptor != null;
}
return byFqNameAndInnerClassList(DescriptorUtils.getFQName(descriptor).toSafe(), innerClassNames);
}
@NotNull
private static String fqNameToInternalName(@NotNull FqName fqName) {
return fqName.asString().replace('.', '/');
}
@NotNull
private static String signatureNameToInternalName(@NotNull String signatureName) {
return signatureName.replace('.', '$');
}
@NotNull
private static String internalNameToFqName(@NotNull String name) {
return decodeSpecialNames(encodeSpecialNames(name).replace('$', '.').replace('/', '.'));
}
@NotNull
private static String internalNameToSignatureName(@NotNull String name) {
return decodeSpecialNames(encodeSpecialNames(name).replace('$', '.'));
}
@NotNull
private static String signatureNameToFqName(@NotNull String name) {
return name.replace('/', '.');
}
private final static String CLASS_OBJECT_REPLACE_GUARD = "<class_object>";
private final static String TRAIT_IMPL_REPLACE_GUARD = "<trait_impl>";
// Internal name: jet/Map$Entry
// FqName: jet.Map.Entry
// Signature name: jet/Map.Entry
private final String internalName;
private FqName fqName;
private String descriptor;
private String signatureName;
private Type asmType;
private JvmClassName(@NotNull String internalName) {
this.internalName = internalName;
}
@NotNull
public FqName getFqName() {
if (fqName == null) {
this.fqName = new FqName(internalNameToFqName(internalName));
}
return fqName;
}
@NotNull
public String getInternalName() {
return internalName;
}
@NotNull
public String getDescriptor() {
if (descriptor == null) {
StringBuilder sb = new StringBuilder(internalName.length() + 2);
sb.append('L');
sb.append(internalName);
sb.append(';');
descriptor = sb.toString();
}
return descriptor;
}
@NotNull
public Type getAsmType() {
if (asmType == null) {
asmType = Type.getType(getDescriptor());
}
return asmType;
}
@NotNull
public String getSignatureName() {
if (signatureName == null) {
signatureName = internalNameToSignatureName(internalName);
}
return signatureName;
}
@NotNull
public FqName getOuterClassFqName() {
String signatureName = getSignatureName();
int index = signatureName.indexOf('.');
String outerClassName = index != -1 ? signatureName.substring(0, index) : signatureName;
return new FqName(signatureNameToFqName(outerClassName));
}
@NotNull
public List<String> getInnerClassNameList() {
List<String> innerClassList = new ArrayList<String>();
String signatureName = getSignatureName();
int index = signatureName.indexOf('.');
while (index != -1) {
int nextIndex = signatureName.indexOf('.', index + 1);
String innerClassName = nextIndex != -1 ? signatureName.substring(index + 1, nextIndex) : signatureName.substring(index + 1);
innerClassList.add(innerClassName);
index = nextIndex;
}
return innerClassList;
}
@Override
public String toString() {
return getInternalName();
}
@Override
public boolean equals(Object o) {
// generated by Idea
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
JvmClassName name = (JvmClassName) o;
if (!internalName.equals(name.internalName)) return false;
return true;
}
@Override
public int hashCode() {
// generated by Idea
return internalName.hashCode();
}
}
@@ -1,124 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Type;
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
import java.util.HashMap;
import java.util.Map;
public enum JvmPrimitiveType {
BOOLEAN(PrimitiveType.BOOLEAN, "boolean", "java.lang.Boolean", Type.BOOLEAN_TYPE),
CHAR(PrimitiveType.CHAR, "char", "java.lang.Character", Type.CHAR_TYPE),
BYTE(PrimitiveType.BYTE, "byte", "java.lang.Byte", Type.BYTE_TYPE),
SHORT(PrimitiveType.SHORT, "short", "java.lang.Short", Type.SHORT_TYPE),
INT(PrimitiveType.INT, "int", "java.lang.Integer", Type.INT_TYPE),
FLOAT(PrimitiveType.FLOAT, "float", "java.lang.Float", Type.FLOAT_TYPE),
LONG(PrimitiveType.LONG, "long", "java.lang.Long", Type.LONG_TYPE),
DOUBLE(PrimitiveType.DOUBLE, "double", "java.lang.Double", Type.DOUBLE_TYPE),
;
private final PrimitiveType primitiveType;
private final String name;
private final JvmClassName wrapper;
private final Type asmType;
private final char jvmLetter;
private final Type asmArrayType;
private final JvmClassName iterator;
private JvmPrimitiveType(PrimitiveType primitiveType, String name, String wrapperClassName, Type asmType) {
this.primitiveType = primitiveType;
this.name = name;
this.wrapper = JvmClassName.byFqNameWithoutInnerClasses(wrapperClassName);
this.asmType = asmType;
this.jvmLetter = asmType.getDescriptor().charAt(0);
this.asmArrayType = makeArrayType(asmType);
this.iterator = JvmClassName.byFqNameWithoutInnerClasses("jet." + primitiveType.getTypeName() + "Iterator");
}
private static Type makeArrayType(Type type) {
StringBuilder sb = new StringBuilder(2);
sb.append('[');
sb.append(type.getDescriptor());
return Type.getType(sb.toString());
}
public PrimitiveType getPrimitiveType() {
return primitiveType;
}
public String getName() {
return name;
}
public JvmClassName getWrapper() {
return wrapper;
}
public Type getAsmType() {
return asmType;
}
public Type getAsmArrayType() {
return asmArrayType;
}
public JvmClassName getIterator() {
return iterator;
}
public char getJvmLetter() {
return jvmLetter;
}
private static class MapByAsmTypeHolder {
private static final Map<Integer, JvmPrimitiveType> map;
static {
map = new HashMap<Integer, JvmPrimitiveType>();
for (JvmPrimitiveType jvmPrimitiveType : values()) {
map.put(jvmPrimitiveType.getAsmType().getSort(), jvmPrimitiveType);
}
}
}
@Nullable
public static JvmPrimitiveType getByAsmType(Type type) {
return MapByAsmTypeHolder.map.get(type.getSort());
}
private static class MapByWrapperAsmTypeHolder {
private static final Map<Type, JvmPrimitiveType> map;
static {
map = new HashMap<Type, JvmPrimitiveType>();
for (JvmPrimitiveType jvmPrimitiveType : values()) {
map.put(jvmPrimitiveType.getWrapper().getAsmType(), jvmPrimitiveType);
}
}
}
@Nullable
public static JvmPrimitiveType getByWrapperAsmType(Type type) {
return MapByWrapperAsmTypeHolder.map.get(type);
}
}
@@ -1,49 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
public final class PackageClassUtils {
private static final String DEFAULT_PACKAGE = "_DefaultPackage";
private PackageClassUtils() {
}
// ex. <root> -> _DefaultPackage, a -> APackage, a.b -> BPackage
public static String getPackageClassName(@NotNull FqName packageFQN) {
if (packageFQN.isRoot()) {
return DEFAULT_PACKAGE;
}
return StringUtil.capitalize(packageFQN.shortName().asString()) + "Package";
}
public static FqName getPackageClassFqName(@NotNull FqName packageFQN) {
return packageFQN.child(Name.identifier(getPackageClassName(packageFQN)));
}
public static boolean isPackageClassFqName(@NotNull FqName fqName) {
if (fqName.isRoot()) {
return false;
}
return getPackageClassFqName(fqName.parent()).equals(fqName);
}
}
@@ -1,31 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.name.FqName;
public interface PsiClassFinder {
@Nullable
PsiClass findPsiClass(@NotNull FqName fqName);
@Nullable
PsiPackage findPsiPackage(@NotNull FqName fqName);
}
@@ -1,72 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.descriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptorLite;
import org.jetbrains.jet.lang.resolve.java.scope.JavaClassNonStaticMembersScope;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collection;
/**
* @see org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyClassDescriptor
*/
public class ClassDescriptorFromJvmBytecode extends MutableClassDescriptorLite {
private JetType functionTypeForSamInterface;
private JavaClassNonStaticMembersScope scopeForConstructorResolve;
public ClassDescriptorFromJvmBytecode(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull ClassKind kind,
boolean isInner
) {
super(containingDeclaration, kind, isInner);
}
@NotNull
@Override
public Collection<ConstructorDescriptor> getConstructors() {
assert scopeForConstructorResolve != null;
return scopeForConstructorResolve.getConstructors();
}
@Nullable
@Override
public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
return scopeForConstructorResolve.getPrimaryConstructor();
}
public void setScopeForConstructorResolve(@NotNull JavaClassNonStaticMembersScope scopeForConstructorResolve) {
this.scopeForConstructorResolve = scopeForConstructorResolve;
}
@Nullable
public JetType getFunctionTypeForSamInterface() {
return functionTypeForSamInterface;
}
public void setFunctionTypeForSamInterface(@NotNull JetType functionTypeForSamInterface) {
this.functionTypeForSamInterface = functionTypeForSamInterface;
}
}
@@ -1,22 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.descriptor;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
public interface JavaCallableMemberDescriptor extends CallableMemberDescriptor {
}
@@ -1,35 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.descriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.List;
public class JavaMethodDescriptor extends SimpleFunctionDescriptorImpl implements JavaCallableMemberDescriptor {
public JavaMethodDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull Name name
) {
super(containingDeclaration, annotations, name, Kind.DECLARATION);
}
}
@@ -1,53 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.descriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.impl.AbstractNamespaceDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorParent;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import java.util.List;
public class JavaNamespaceDescriptor extends AbstractNamespaceDescriptorImpl {
private JetScope memberScope;
private final FqName qualifiedName;
public JavaNamespaceDescriptor(NamespaceDescriptorParent containingDeclaration, List<AnnotationDescriptor> annotations,
@NotNull FqName qualifiedName) {
super(containingDeclaration, annotations, qualifiedName.shortNameOrSpecial());
this.qualifiedName = qualifiedName;
}
public void setMemberScope(@NotNull JetScope memberScope) {
this.memberScope = memberScope;
}
@NotNull
@Override
public JetScope getMemberScope() {
return memberScope;
}
@NotNull
@Override
public FqName getFqName() {
return qualifiedName;
}
}
@@ -1,39 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.descriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.Modality;
import org.jetbrains.jet.lang.descriptors.Visibility;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.List;
public class JavaPropertyDescriptor extends PropertyDescriptorImpl implements JavaCallableMemberDescriptor {
public JavaPropertyDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull Visibility visibility,
boolean isVar,
@NotNull Name name
) {
super(containingDeclaration, annotations, Modality.FINAL, visibility, isVar, name, Kind.DECLARATION);
}
}
@@ -1,39 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.descriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.Visibility;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorForObjectImpl;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.List;
public class JavaPropertyDescriptorForObject extends PropertyDescriptorForObjectImpl implements JavaCallableMemberDescriptor {
public JavaPropertyDescriptorForObject(
@NotNull ClassOrNamespaceDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull Visibility visibility,
@NotNull Name name,
@NotNull ClassDescriptor objectClass
) {
super(containingDeclaration, annotations, visibility, name, objectClass);
}
}
@@ -1,23 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.descriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.SynthesizedCallableMemberDescriptor;
public interface SamAdapterDescriptor<D extends FunctionDescriptor> extends FunctionDescriptor, SynthesizedCallableMemberDescriptor<D> {
}
@@ -1,41 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.descriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.SynthesizedCallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
public class SamConstructorDescriptor extends SimpleFunctionDescriptorImpl
implements SynthesizedCallableMemberDescriptor<ClassDescriptorFromJvmBytecode> {
private final ClassDescriptorFromJvmBytecode samInterface;
public SamConstructorDescriptor(
@NotNull ClassOrNamespaceDescriptor containingDeclaration,
@NotNull ClassDescriptorFromJvmBytecode samInterface
) {
super(containingDeclaration, samInterface.getAnnotations(), samInterface.getName(), Kind.SYNTHESIZED);
this.samInterface = samInterface;
}
@NotNull
@Override
public ClassDescriptorFromJvmBytecode getBaseForSynthesized() {
return samInterface;
}
}
@@ -1,191 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.mapping;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.constants.StringValue;
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
import org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils;
import org.jetbrains.jet.lang.resolve.java.resolver.JavaAnnotationResolver;
import org.jetbrains.jet.lang.resolve.java.resolver.TypeUsage;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
import java.util.*;
public class JavaToKotlinClassMap extends JavaToKotlinClassMapBuilder implements PlatformToKotlinClassMap {
private static final FqName JAVA_LANG_DEPRECATED = new FqName("java.lang.Deprecated");
private static JavaToKotlinClassMap instance = null;
@NotNull
public static JavaToKotlinClassMap getInstance() {
if (instance == null) {
instance = new JavaToKotlinClassMap();
}
return instance;
}
private final Map<FqName, ClassDescriptor> classDescriptorMap = new HashMap<FqName, ClassDescriptor>();
private final Map<FqName, ClassDescriptor> classDescriptorMapForCovariantPositions = new HashMap<FqName, ClassDescriptor>();
private final Map<String, JetType> primitiveTypesMap = new HashMap<String, JetType>();
private final Multimap<FqName, ClassDescriptor> packagesWithMappedClasses = HashMultimap.create();
private JavaToKotlinClassMap() {
init();
initPrimitives();
}
private void initPrimitives() {
KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
register(jvmPrimitiveType.getWrapper().getFqName(), builtIns.getPrimitiveClassDescriptor(primitiveType));
}
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
primitiveTypesMap.put(jvmPrimitiveType.getName(), KotlinBuiltIns.getInstance().getPrimitiveJetType(primitiveType));
primitiveTypesMap.put("[" + jvmPrimitiveType.getName(), KotlinBuiltIns.getInstance().getPrimitiveArrayJetType(primitiveType));
primitiveTypesMap.put(jvmPrimitiveType.getWrapper().getFqName().asString(), KotlinBuiltIns.getInstance().getNullablePrimitiveJetType(
primitiveType));
}
primitiveTypesMap.put("void", KotlinBuiltIns.getInstance().getUnitType());
}
@Nullable
public JetType mapPrimitiveKotlinClass(@NotNull String name) {
return primitiveTypesMap.get(name);
}
@Nullable
public ClassDescriptor mapKotlinClass(@NotNull FqName fqName, @NotNull TypeUsage typeUsage) {
if (typeUsage == TypeUsage.MEMBER_SIGNATURE_COVARIANT
|| typeUsage == TypeUsage.SUPERTYPE) {
ClassDescriptor descriptor = classDescriptorMapForCovariantPositions.get(fqName);
if (descriptor != null) {
return descriptor;
}
}
return classDescriptorMap.get(fqName);
}
@Nullable
public AnnotationDescriptor mapToAnnotationClass(@NotNull FqName fqName) {
ClassDescriptor classDescriptor = classDescriptorMap.get(fqName);
if (classDescriptor != null && fqName.equals(JAVA_LANG_DEPRECATED)) {
return getAnnotationDescriptorForJavaLangDeprecated(classDescriptor);
}
return null;
}
@NotNull
private static AnnotationDescriptor getAnnotationDescriptorForJavaLangDeprecated(@NotNull ClassDescriptor annotationClass) {
AnnotationDescriptor annotation = new AnnotationDescriptor();
annotation.setAnnotationType(annotationClass.getDefaultType());
ValueParameterDescriptor value = DescriptorResolverUtils.getAnnotationParameterByName(
JavaAnnotationResolver.DEFAULT_ANNOTATION_MEMBER_NAME, annotationClass);
assert value != null : "jet.deprecated must have one parameter called value";
annotation.setValueArgument(value, new StringValue("Deprecated in Java"));
return annotation;
}
private static FqName getJavaClassFqName(@NotNull Class<?> javaClass) {
return new FqName(javaClass.getName().replace('$', '.'));
}
@Override
protected void register(
@NotNull Class<?> javaClass,
@NotNull ClassDescriptor kotlinDescriptor,
@NotNull Direction direction
) {
if (direction == Direction.BOTH || direction == Direction.JAVA_TO_KOTLIN) {
register(getJavaClassFqName(javaClass), kotlinDescriptor);
}
}
@Override
protected void register(
@NotNull Class<?> javaClass,
@NotNull ClassDescriptor kotlinDescriptor,
@NotNull ClassDescriptor kotlinMutableDescriptor,
@NotNull Direction direction
) {
if (direction == Direction.BOTH || direction == Direction.JAVA_TO_KOTLIN) {
FqName javaClassName = getJavaClassFqName(javaClass);
register(javaClassName, kotlinDescriptor);
registerCovariant(javaClassName, kotlinMutableDescriptor);
}
}
private void register(@NotNull FqName javaClassName, @NotNull ClassDescriptor kotlinDescriptor) {
classDescriptorMap.put(javaClassName, kotlinDescriptor);
packagesWithMappedClasses.put(javaClassName.parent(), kotlinDescriptor);
}
private void registerCovariant(@NotNull FqName javaClassName, @NotNull ClassDescriptor kotlinDescriptor) {
classDescriptorMapForCovariantPositions.put(javaClassName, kotlinDescriptor);
packagesWithMappedClasses.put(javaClassName.parent(), kotlinDescriptor);
}
@NotNull
public Collection<ClassDescriptor> mapPlatformClass(@NotNull FqName fqName) {
ClassDescriptor kotlinAnalog = classDescriptorMap.get(fqName);
ClassDescriptor kotlinCovariantAnalog = classDescriptorMapForCovariantPositions.get(fqName);
List<ClassDescriptor> descriptors = new ArrayList<ClassDescriptor>(2);
if (kotlinAnalog != null) {
descriptors.add(kotlinAnalog);
}
if (kotlinCovariantAnalog != null) {
descriptors.add(kotlinCovariantAnalog);
}
return descriptors;
}
@Override
@NotNull
public Collection<ClassDescriptor> mapPlatformClass(@NotNull ClassDescriptor classDescriptor) {
FqNameUnsafe className = DescriptorUtils.getFQName(classDescriptor);
if (!className.isSafe()) {
return Collections.emptyList();
}
return mapPlatformClass(className.toSafe());
}
@Override
@NotNull
public Collection<ClassDescriptor> mapPlatformClassesInside(@NotNull DeclarationDescriptor containingDeclaration) {
FqNameUnsafe fqName = DescriptorUtils.getFQName(containingDeclaration);
if (!fqName.isSafe()) {
return Collections.emptyList();
}
return packagesWithMappedClasses.get(fqName.toSafe());
}
}
@@ -1,66 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.mapping;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import java.lang.annotation.Annotation;
import java.util.*;
public abstract class JavaToKotlinClassMapBuilder {
public enum Direction {
JAVA_TO_KOTLIN,
KOTLIN_TO_JAVA,
BOTH
}
protected void init() {
KotlinBuiltIns kotlinBuiltIns = KotlinBuiltIns.getInstance();
register(Object.class, KotlinBuiltIns.getInstance().getAny());
register(String.class, kotlinBuiltIns.getString());
register(CharSequence.class, kotlinBuiltIns.getCharSequence());
register(Throwable.class, kotlinBuiltIns.getThrowable());
register(Number.class, kotlinBuiltIns.getNumber());
register(Comparable.class, kotlinBuiltIns.getComparable());
register(Enum.class, kotlinBuiltIns.getEnum());
register(Annotation.class, kotlinBuiltIns.getAnnotation());
register(Deprecated.class, kotlinBuiltIns.getDeprecatedAnnotation(), Direction.JAVA_TO_KOTLIN);
register(Iterable.class, kotlinBuiltIns.getIterable(), kotlinBuiltIns.getMutableIterable());
register(Iterator.class, kotlinBuiltIns.getIterator(), kotlinBuiltIns.getMutableIterator());
register(Collection.class, kotlinBuiltIns.getCollection(), kotlinBuiltIns.getMutableCollection());
register(List.class, kotlinBuiltIns.getList(), kotlinBuiltIns.getMutableList());
register(Set.class, kotlinBuiltIns.getSet(), kotlinBuiltIns.getMutableSet());
register(Map.class, kotlinBuiltIns.getMap(), kotlinBuiltIns.getMutableMap());
register(Map.Entry.class, kotlinBuiltIns.getMapEntry(), kotlinBuiltIns.getMutableMapEntry());
register(ListIterator.class, kotlinBuiltIns.getListIterator(), kotlinBuiltIns.getMutableListIterator());
}
/*package*/ void register(@NotNull Class<?> javaClass, @NotNull ClassDescriptor kotlinDescriptor) {
register(javaClass, kotlinDescriptor, Direction.BOTH);
}
protected abstract void register(@NotNull Class<?> javaClass, @NotNull ClassDescriptor kotlinDescriptor, @NotNull Direction direction);
/*package*/ void register(@NotNull Class<?> javaClass, @NotNull ClassDescriptor kotlinDescriptor, @NotNull ClassDescriptor kotlinMutableDescriptor) {
register(javaClass, kotlinDescriptor, kotlinMutableDescriptor, Direction.BOTH);
}
protected abstract void register(@NotNull Class<?> javaClass, @NotNull ClassDescriptor kotlinDescriptor, @NotNull ClassDescriptor kotlinMutableDescriptor, @NotNull Direction direction);
}
@@ -1,116 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.mapping;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Type;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
import java.util.HashMap;
import java.util.Map;
public class KotlinToJavaTypesMap extends JavaToKotlinClassMapBuilder {
private static KotlinToJavaTypesMap instance = null;
@NotNull
public static KotlinToJavaTypesMap getInstance() {
if (instance == null) {
instance = new KotlinToJavaTypesMap();
}
return instance;
}
private final Map<FqName, Type> asmTypes = new HashMap<FqName, Type>();
private final Map<FqName, Type> asmNullableTypes = new HashMap<FqName, Type>();
private KotlinToJavaTypesMap() {
init();
initPrimitives();
}
private void initPrimitives() {
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
FqName className = jvmPrimitiveType.getPrimitiveType().getClassName();
register(className, jvmPrimitiveType.getAsmType());
registerNullable(className, jvmPrimitiveType.getWrapper().getAsmType());
}
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
register(primitiveType.getArrayClassName(), jvmPrimitiveType.getAsmArrayType());
}
}
@Nullable
public Type getJavaAnalog(@NotNull JetType jetType) {
ClassifierDescriptor classifier = jetType.getConstructor().getDeclarationDescriptor();
assert classifier != null;
FqNameUnsafe className = DescriptorUtils.getFQName(classifier);
if (!className.isSafe()) return null;
FqName fqName = className.toSafe();
if (jetType.isNullable()) {
Type nullableType = asmNullableTypes.get(fqName);
if (nullableType != null) {
return nullableType;
}
}
return asmTypes.get(fqName);
}
@Override
protected void register(@NotNull Class<?> javaClass, @NotNull ClassDescriptor kotlinDescriptor, @NotNull Direction direction) {
if (direction == Direction.BOTH || direction == Direction.KOTLIN_TO_JAVA) {
register(kotlinDescriptor, AsmTypeConstants.getType(javaClass));
}
}
@Override
protected void register(
@NotNull Class<?> javaClass,
@NotNull ClassDescriptor kotlinDescriptor,
@NotNull ClassDescriptor kotlinMutableDescriptor,
@NotNull Direction direction
) {
if (direction == Direction.BOTH || direction == Direction.KOTLIN_TO_JAVA) {
register(javaClass, kotlinDescriptor);
register(javaClass, kotlinMutableDescriptor);
}
}
private void register(@NotNull ClassDescriptor kotlinDescriptor, @NotNull Type javaType) {
FqNameUnsafe fqName = DescriptorUtils.getFQName(kotlinDescriptor);
assert fqName.isSafe();
register(fqName.toSafe(), javaType);
}
private void register(@NotNull FqName fqName, @NotNull Type type) {
asmTypes.put(fqName, type);
}
private void registerNullable(@NotNull FqName fqName, @NotNull Type nullableType) {
asmNullableTypes.put(fqName, nullableType);
}
}
@@ -1,408 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.*;
import org.jetbrains.asm4.commons.Method;
import org.jetbrains.jet.descriptors.serialization.ClassId;
import org.jetbrains.jet.descriptors.serialization.JavaProtoBufUtil;
import org.jetbrains.jet.descriptors.serialization.NameResolver;
import org.jetbrains.jet.descriptors.serialization.ProtoBuf;
import org.jetbrains.jet.descriptors.serialization.descriptors.AnnotationDeserializer;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.constants.EnumValue;
import org.jetbrains.jet.lang.resolve.java.*;
import org.jetbrains.jet.lang.resolve.java.vfilefinder.VirtualFileFinder;
import org.jetbrains.jet.lang.resolve.lazy.storage.LockBasedStorageManager;
import org.jetbrains.jet.lang.resolve.lazy.storage.MemoizedFunctionToNotNull;
import org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.utils.ExceptionUtils;
import javax.inject.Inject;
import java.io.IOException;
import java.util.*;
import static org.jetbrains.asm4.ClassReader.*;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.IGNORE_KOTLIN_SOURCES;
import static org.jetbrains.jet.lang.resolve.java.resolver.DeserializedResolverUtils.*;
public class AnnotationDescriptorDeserializer implements AnnotationDeserializer {
private PsiClassFinder psiClassFinder;
private JavaClassResolver javaClassResolver;
private VirtualFileFinder virtualFileFinder;
// TODO: a single instance of StorageManager for all computations in resolve-java
private final LockBasedStorageManager storageManager = new LockBasedStorageManager();
private final MemoizedFunctionToNotNull<VirtualFile, Map<MemberSignature, List<AnnotationDescriptor>>> memberAnnotations =
storageManager.createMemoizedFunction(
new MemoizedFunctionToNotNull<VirtualFile, Map<MemberSignature, List<AnnotationDescriptor>>>() {
@NotNull
@Override
public Map<MemberSignature, List<AnnotationDescriptor>> fun(@NotNull VirtualFile file) {
try {
return loadMemberAnnotationsFromFile(file);
}
catch (IOException e) {
throw ExceptionUtils.rethrow(e);
}
}
}, StorageManager.ReferenceKind.STRONG);
@Inject
public void setPsiClassFinder(PsiClassFinder psiClassFinder) {
this.psiClassFinder = psiClassFinder;
}
@Inject
public void setVirtualFileFinder(VirtualFileFinder virtualFileFinder) {
this.virtualFileFinder = virtualFileFinder;
}
@Inject
public void setJavaClassResolver(JavaClassResolver javaClassResolver) {
this.javaClassResolver = javaClassResolver;
}
@NotNull
@Override
public List<AnnotationDescriptor> loadClassAnnotations(@NotNull ClassDescriptor descriptor, @NotNull ProtoBuf.Class classProto) {
VirtualFile virtualFile = findVirtualFileByClass(descriptor);
try {
return loadClassAnnotationsFromFile(virtualFile);
}
catch (IOException e) {
throw ExceptionUtils.rethrow(e);
}
}
@NotNull
private VirtualFile findVirtualFileByDescriptor(@NotNull ClassOrNamespaceDescriptor descriptor) {
if (descriptor instanceof ClassDescriptor) {
return findVirtualFileByClass((ClassDescriptor) descriptor);
}
else if (descriptor instanceof NamespaceDescriptor) {
return findVirtualFileByPackage((NamespaceDescriptor) descriptor);
}
else {
throw new IllegalStateException("Unrecognized descriptor: " + descriptor);
}
}
@NotNull
private VirtualFile findVirtualFileByClass(@NotNull ClassDescriptor descriptor) {
FqName fqName = kotlinFqNameToJavaFqName(naiveKotlinFqName(descriptor));
VirtualFile fileForKotlinFile = virtualFileFinder.find(fqName);
if (fileForKotlinFile != null) {
return fileForKotlinFile;
}
PsiClass psiClass = psiClassFinder.findPsiClass(fqName);
if (psiClass == null) {
throw new IllegalStateException("Psi class is not found for class: " + descriptor);
}
VirtualFile outerClassFile = psiClass.getContainingFile().getVirtualFile();
if (outerClassFile == null) {
throw new IllegalStateException("Outer class file is not found for class: " + descriptor);
}
ClassId id = ClassId.fromFqNameAndContainingDeclaration(fqName, (ClassOrNamespaceDescriptor) descriptor.getContainingDeclaration());
VirtualFile virtualFile = getVirtualFile(id, outerClassFile);
if (virtualFile == null) {
throw new IllegalStateException("Virtual file is not found for class: " + descriptor);
}
return virtualFile;
}
@NotNull
private VirtualFile findVirtualFileByPackage(@NotNull NamespaceDescriptor descriptor) {
FqName fqName = PackageClassUtils.getPackageClassFqName(DescriptorUtils.getFQName(descriptor).toSafe());
VirtualFile virtualFile = virtualFileFinder.find(fqName);
if (virtualFile == null) {
throw new IllegalStateException("Virtual file is not found for package: " + descriptor);
}
return virtualFile;
}
@NotNull
private List<AnnotationDescriptor> loadClassAnnotationsFromFile(@NotNull VirtualFile virtualFile) throws IOException {
final List<AnnotationDescriptor> result = new ArrayList<AnnotationDescriptor>();
new ClassReader(virtualFile.getInputStream()).accept(new ClassVisitor(Opcodes.ASM4) {
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
return resolveAnnotation(desc, result);
}
}, SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES);
return result;
}
private static boolean ignoreAnnotation(@NotNull String desc) {
// TODO: JvmAbi.JETBRAINS_NOT_NULL_ANNOTATION ?
return desc.equals(JvmAnnotationNames.KOTLIN_CLASS.getDescriptor())
|| desc.equals(JvmAnnotationNames.KOTLIN_PACKAGE.getDescriptor())
|| desc.startsWith("Ljet/runtime/typeinfo/");
}
@NotNull
private static FqName convertJvmDescriptorToFqName(@NotNull String desc) {
assert desc.startsWith("L") && desc.endsWith(";") : "Not a JVM descriptor: " + desc;
String fqName = desc.substring(1, desc.length() - 1).replace('$', '.').replace('/', '.');
return new FqName(fqName);
}
@Nullable
private AnnotationVisitor resolveAnnotation(@NotNull String desc, @NotNull final List<AnnotationDescriptor> result) {
if (ignoreAnnotation(desc)) return null;
FqName annotationFqName = convertJvmDescriptorToFqName(desc);
final ClassDescriptor annotationClass = javaClassResolver.resolveClass(annotationFqName, IGNORE_KOTLIN_SOURCES);
assert annotationClass != null : "Annotation class is not found: " + desc;
final AnnotationDescriptor annotation = new AnnotationDescriptor();
annotation.setAnnotationType(annotationClass.getDefaultType());
return new AnnotationVisitor(Opcodes.ASM4) {
// TODO: arrays, annotations
@Override
public void visit(String name, Object value) {
CompileTimeConstant<?> argument = JavaAnnotationArgumentResolver.resolveCompileTimeConstantValue(value, null);
if (argument != null) {
setArgumentValueByName(name, argument);
}
}
@Override
public void visitEnum(String name, String desc, String value) {
FqName fqName = convertJvmDescriptorToFqName(desc);
ClassDescriptor enumClass = javaClassResolver.resolveClass(fqName, IGNORE_KOTLIN_SOURCES);
assert enumClass != null : "Enum class referenced in annotation is not found: " + desc;
JetScope scope = DescriptorUtils.getEnumEntriesScope(enumClass);
Collection<VariableDescriptor> properties = scope.getProperties(Name.identifier(value));
assert properties.size() == 1 : "Enum class should have exactly one property with the referenced name: " + value +
"\n" + properties + "\n" + enumClass;
EnumValue enumValue = new EnumValue((PropertyDescriptor) properties.iterator().next());
setArgumentValueByName(name, enumValue);
}
@Override
public void visitEnd() {
result.add(annotation);
}
private void setArgumentValueByName(@NotNull String name, @NotNull CompileTimeConstant<?> argumentValue) {
ValueParameterDescriptor parameter =
DescriptorResolverUtils.getAnnotationParameterByName(Name.identifier(name), annotationClass);
if (parameter != null) {
annotation.setValueArgument(parameter, argumentValue);
}
}
};
}
@NotNull
@Override
public List<AnnotationDescriptor> loadCallableAnnotations(
@NotNull ClassOrNamespaceDescriptor container,
@NotNull ProtoBuf.Callable proto,
@NotNull NameResolver nameResolver,
@NotNull AnnotatedCallableKind kind
) {
MemberSignature signature = getCallableSignature(proto, nameResolver, kind);
if (signature == null) return Collections.emptyList();
VirtualFile file = getVirtualFileWithMemberAnnotations(container, proto, nameResolver);
List<AnnotationDescriptor> annotations = memberAnnotations.fun(file).get(signature);
return annotations == null ? Collections.<AnnotationDescriptor>emptyList() : annotations;
}
@NotNull
private VirtualFile getVirtualFileWithMemberAnnotations(
@NotNull ClassOrNamespaceDescriptor container,
@NotNull ProtoBuf.Callable proto,
@NotNull NameResolver nameResolver
) {
if (container instanceof NamespaceDescriptor) {
Name name = JavaProtoBufUtil.loadSrcClassName(proto, nameResolver);
if (name != null) {
// To locate a package$src class, we first find the facade virtual file (*Package.class) and then look up the $src file in
// the same directory. This hack is needed because FileManager doesn't find classfiles for $src classes
VirtualFile facadeFile = findVirtualFileByPackage((NamespaceDescriptor) container);
VirtualFile srcFile = facadeFile.getParent().findChild(name + ".class");
if (srcFile != null) {
return srcFile;
}
}
}
else if (container instanceof ClassDescriptor && ((ClassDescriptor) container).getKind() == ClassKind.CLASS_OBJECT) {
// Backing fields of properties of a class object are generated in the outer class
if (JavaProtoBufUtil.isStaticFieldInOuter(proto)) {
return findVirtualFileByDescriptor((ClassOrNamespaceDescriptor) container.getContainingDeclaration());
}
}
return findVirtualFileByDescriptor(container);
}
@Nullable
private static MemberSignature getCallableSignature(
@NotNull ProtoBuf.Callable proto,
@NotNull NameResolver nameResolver,
@NotNull AnnotatedCallableKind kind
) {
switch (kind) {
case FUNCTION:
return MemberSignature.fromMethod(JavaProtoBufUtil.loadMethodSignature(proto, nameResolver));
case PROPERTY_GETTER:
return MemberSignature.fromMethod(JavaProtoBufUtil.loadPropertyGetterSignature(proto, nameResolver));
case PROPERTY_SETTER:
return MemberSignature.fromMethod(JavaProtoBufUtil.loadPropertySetterSignature(proto, nameResolver));
case PROPERTY:
JavaProtoBufUtil.PropertyData data = JavaProtoBufUtil.loadPropertyData(proto, nameResolver);
return data == null ? null :
MemberSignature.fromPropertyData(data.getFieldType(), data.getFieldName(), data.getSyntheticMethodName());
default:
return null;
}
}
@NotNull
private Map<MemberSignature, List<AnnotationDescriptor>> loadMemberAnnotationsFromFile(@NotNull VirtualFile file) throws IOException {
final Map<MemberSignature, List<AnnotationDescriptor>> memberAnnotations =
new HashMap<MemberSignature, List<AnnotationDescriptor>>();
new ClassReader(file.getInputStream()).accept(new ClassVisitor(Opcodes.ASM4) {
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
final MemberSignature methodSignature = MemberSignature.fromMethodNameAndDesc(name, desc);
final List<AnnotationDescriptor> result = new ArrayList<AnnotationDescriptor>();
return new MethodVisitor(Opcodes.ASM4) {
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
return resolveAnnotation(desc, result);
}
@Override
public void visitEnd() {
if (!result.isEmpty()) {
memberAnnotations.put(methodSignature, result);
}
}
};
}
@Override
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
final MemberSignature fieldSignature = MemberSignature.fromFieldNameAndDesc(name, desc);
final List<AnnotationDescriptor> result = new ArrayList<AnnotationDescriptor>();
return new FieldVisitor(Opcodes.ASM4) {
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
return resolveAnnotation(desc, result);
}
@Override
public void visitEnd() {
if (!result.isEmpty()) {
memberAnnotations.put(fieldSignature, result);
}
}
};
}
}, SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES);
return memberAnnotations;
}
// The purpose of this class is to hold a unique signature of either a method or a field, so that annotations on a member can be put
// into a map indexed by these signatures
private static final class MemberSignature {
private final String signature;
private MemberSignature(@NotNull String signature) {
this.signature = signature;
}
@Nullable
public static MemberSignature fromPropertyData(
@Nullable Type fieldType,
@Nullable String fieldName,
@Nullable String syntheticMethodName
) {
if (fieldName != null && fieldType != null) {
return fromFieldNameAndDesc(fieldName, fieldType.getDescriptor());
}
else if (syntheticMethodName != null) {
return fromMethodNameAndDesc(syntheticMethodName, JvmAbi.ANNOTATED_PROPERTY_METHOD_SIGNATURE);
}
else {
return null;
}
}
@Nullable
public static MemberSignature fromMethod(@Nullable Method method) {
return method == null ? null : fromMethodNameAndDesc(method.getName(), method.getDescriptor());
}
@NotNull
public static MemberSignature fromMethodNameAndDesc(@NotNull String name, @NotNull String desc) {
return new MemberSignature(name + desc);
}
@NotNull
public static MemberSignature fromFieldNameAndDesc(@NotNull String name, @NotNull String desc) {
return new MemberSignature(name + "#" + desc);
}
@Override
public int hashCode() {
return signature.hashCode();
}
@Override
public boolean equals(Object o) {
return o instanceof MemberSignature && signature.equals(((MemberSignature) o).signature);
}
@Override
public String toString() {
return signature;
}
}
@NotNull
@Override
public List<AnnotationDescriptor> loadValueParameterAnnotations(@NotNull ProtoBuf.Callable.ValueParameter parameterProto) {
throw new UnsupportedOperationException(); // TODO
}
}
@@ -1,260 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.jet.lang.resolve.OverrideResolver;
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
import org.jetbrains.jet.lang.resolve.java.structure.*;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isEnumClassObject;
public final class DescriptorResolverUtils {
private DescriptorResolverUtils() {
}
public static boolean isCompiledKotlinPackageClass(@NotNull JavaClass javaClass) {
if (javaClass.getOriginKind() == JavaClass.OriginKind.COMPILED) {
FqName fqName = javaClass.getFqName();
if (fqName != null && PackageClassUtils.isPackageClassFqName(fqName)) {
return javaClass.findAnnotation(JvmAnnotationNames.KOTLIN_PACKAGE.getFqName()) != null;
}
}
return false;
}
public static boolean isCompiledKotlinClass(@NotNull JavaClass javaClass) {
if (javaClass.getOriginKind() == JavaClass.OriginKind.COMPILED) {
return javaClass.findAnnotation(JvmAnnotationNames.KOTLIN_CLASS.getFqName()) != null;
}
return false;
}
public static boolean isCompiledKotlinClassOrPackageClass(@NotNull JavaClass javaClass) {
return isCompiledKotlinClass(javaClass) || isCompiledKotlinPackageClass(javaClass);
}
@NotNull
public static <D extends CallableMemberDescriptor> Collection<D> resolveOverrides(
@NotNull Name name,
@NotNull Collection<D> membersFromSupertypes,
@NotNull Collection<D> membersFromCurrent,
@NotNull ClassDescriptor classDescriptor,
@NotNull final FakeOverrideVisibilityResolver visibilityResolver
) {
final Set<D> result = new HashSet<D>();
OverrideResolver.generateOverridesInFunctionGroup(
name, membersFromSupertypes, membersFromCurrent, classDescriptor,
new OverrideResolver.DescriptorSink() {
@Override
@SuppressWarnings("unchecked")
public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
visibilityResolver.resolveUnknownVisibilityForMember(fakeOverride);
result.add((D) fakeOverride);
}
@Override
public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
// nop
}
}
);
return result;
}
@Nullable
public static ValueParameterDescriptor getAnnotationParameterByName(@NotNull Name name, @NotNull ClassDescriptor annotationClass) {
Collection<ConstructorDescriptor> constructors = annotationClass.getConstructors();
assert constructors.size() == 1 : "Annotation class descriptor must have only one constructor";
for (ValueParameterDescriptor parameter : constructors.iterator().next().getValueParameters()) {
if (parameter.getName().equals(name)) {
return parameter;
}
}
return null;
}
/**
* @return true if {@code member} is a static member of enum class, which is to be put into its class object (and not into the
* corresponding package). This applies to enum entries, values() and valueOf(String) methods
*/
public static boolean shouldBeInEnumClassObject(@NotNull JavaMember member) {
if (!member.getContainingClass().isEnum()) return false;
if (member instanceof JavaField && ((JavaField) member).isEnumEntry()) return true;
if (!(member instanceof JavaMethod)) return false;
String signature = JavaSignatureFormatter.getInstance().formatMethod((JavaMethod) member);
return "values()".equals(signature) ||
"valueOf(java.lang.String)".equals(signature);
}
public static boolean isCorrectOwnerForEnumMember(@NotNull ClassOrNamespaceDescriptor ownerDescriptor, @NotNull JavaMember member) {
return isEnumClassObject(ownerDescriptor) == shouldBeInEnumClassObject(member);
}
public static boolean isObjectMethodInInterface(@NotNull JavaMember member) {
return member.getContainingClass().isInterface() && member instanceof JavaMethod && isObjectMethod((JavaMethod) member);
}
public static boolean isObjectMethod(@NotNull JavaMethod method) {
String signature = JavaSignatureFormatter.getInstance().formatMethod(method);
return "hashCode()".equals(signature) ||
"equals(java.lang.Object)".equals(signature) ||
"toString()".equals(signature);
}
@NotNull
public static Collection<JavaClass> getClassesInPackage(@NotNull JavaPackage javaPackage) {
Collection<JavaClass> classes = javaPackage.getClasses();
Set<FqName> addedQualifiedNames = new HashSet<FqName>(classes.size());
List<JavaClass> result = new ArrayList<JavaClass>(classes.size());
for (JavaClass javaClass : classes) {
FqName fqName = javaClass.getFqName();
if (fqName != null && addedQualifiedNames.add(fqName)) {
result.add(javaClass);
}
}
return result;
}
/**
* @see com.intellij.psi.util.TypeConversionUtil#erasure(com.intellij.psi.PsiType)
*/
@Nullable
public static JavaType erasure(@NotNull JavaType type) {
return erasure(type, JavaTypeSubstitutor.EMPTY);
}
/**
* @see com.intellij.psi.util.TypeConversionUtil#erasure(com.intellij.psi.PsiType, com.intellij.psi.PsiSubstitutor)
*/
@Nullable
public static JavaType erasure(@NotNull JavaType type, @NotNull JavaTypeSubstitutor substitutor) {
if (type instanceof JavaClassifierType) {
JavaClassifier classifier = ((JavaClassifierType) type).getClassifier();
if (classifier instanceof JavaClass) {
return ((JavaClass) classifier).getDefaultType();
}
else if (classifier instanceof JavaTypeParameter) {
JavaTypeParameter typeParameter = (JavaTypeParameter) classifier;
return typeParameterErasure(typeParameter, new HashSet<JavaTypeParameter>(), substitutor);
}
else {
return null;
}
}
else if (type instanceof JavaPrimitiveType) {
return type;
}
else if (type instanceof JavaArrayType) {
JavaType erasure = erasure(((JavaArrayType) type).getComponentType(), substitutor);
return erasure == null ? null : JavaElementFactory.getInstance().createArrayType(erasure);
}
else if (type instanceof JavaWildcardType) {
JavaWildcardType wildcardType = (JavaWildcardType) type;
JavaType bound = wildcardType.getBound();
if (bound != null && wildcardType.isExtends()) {
return erasure(bound, substitutor);
}
return wildcardType.getTypeProvider().createJavaLangObjectType();
}
else {
throw new IllegalStateException("Unsupported type: " + type);
}
}
/**
* @see com.intellij.psi.util.TypeConversionUtil#typeParameterErasure(com.intellij.psi.PsiTypeParameter)
*/
@Nullable
private static JavaType typeParameterErasure(
@NotNull JavaTypeParameter typeParameter,
@NotNull HashSet<JavaTypeParameter> visited,
@NotNull JavaTypeSubstitutor substitutor
) {
Collection<JavaClassifierType> upperBounds = typeParameter.getUpperBounds();
if (!upperBounds.isEmpty()) {
JavaClassifier classifier = upperBounds.iterator().next().getClassifier();
if (classifier instanceof JavaTypeParameter && !visited.contains(classifier)) {
JavaTypeParameter typeParameterBound = (JavaTypeParameter) classifier;
visited.add(typeParameterBound);
JavaType substitutedType = substitutor.substitute(typeParameterBound);
if (substitutedType != null) {
return erasure(substitutedType);
}
return typeParameterErasure(typeParameterBound, visited, substitutor);
}
else if (classifier instanceof JavaClass) {
return ((JavaClass) classifier).getDefaultType();
}
}
return typeParameter.getTypeProvider().createJavaLangObjectType();
}
@NotNull
public static Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> recreateTypeParametersAndReturnMapping(
@NotNull List<TypeParameterDescriptor> originalParameters,
@Nullable DeclarationDescriptor newOwner
) {
Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> result = Maps.newLinkedHashMap(); // save order of type parameters
for (TypeParameterDescriptor typeParameter : originalParameters) {
result.put(typeParameter,
TypeParameterDescriptorImpl.createForFurtherModification(
newOwner == null ? typeParameter.getContainingDeclaration() : newOwner,
typeParameter.getAnnotations(),
typeParameter.isReified(),
typeParameter.getVariance(),
typeParameter.getName(),
typeParameter.getIndex()));
}
return result;
}
@NotNull
public static TypeSubstitutor createSubstitutorForTypeParameters(
@NotNull Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> originalToAltTypeParameters
) {
Map<TypeConstructor, TypeProjection> typeSubstitutionContext = Maps.newHashMap();
for (Map.Entry<TypeParameterDescriptor, TypeParameterDescriptorImpl> originalToAltTypeParameter : originalToAltTypeParameters
.entrySet()) {
typeSubstitutionContext.put(originalToAltTypeParameter.getKey().getTypeConstructor(),
new TypeProjection(originalToAltTypeParameter.getValue().getDefaultType()));
}
return TypeSubstitutor.create(typeSubstitutionContext);
}
}
@@ -1,136 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.descriptors.serialization.*;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedClassDescriptor;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedPackageMemberScope;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.lazy.storage.LockBasedStorageManager;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import javax.inject.Inject;
import java.util.Collection;
import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCompatible;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.IGNORE_KOTLIN_SOURCES;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.INCLUDE_KOTLIN_SOURCES;
import static org.jetbrains.jet.lang.resolve.java.resolver.DeserializedResolverUtils.kotlinFqNameToJavaFqName;
public final class DeserializedDescriptorResolver {
private AnnotationDescriptorDeserializer annotationDeserializer;
private final LockBasedStorageManager storageManager = new LockBasedStorageManager();
private JavaNamespaceResolver javaNamespaceResolver;
private JavaClassResolver javaClassResolver;
private ErrorReporter errorReporter;
@NotNull
private final DescriptorFinder javaDescriptorFinder = new DescriptorFinder() {
@Nullable
@Override
public ClassDescriptor findClass(@NotNull ClassId classId) {
return javaClassResolver.resolveClass(kotlinFqNameToJavaFqName(classId.asSingleFqName()), IGNORE_KOTLIN_SOURCES);
}
@Nullable
@Override
public NamespaceDescriptor findPackage(@NotNull FqName name) {
return javaNamespaceResolver.resolveNamespace(name, IGNORE_KOTLIN_SOURCES);
}
@NotNull
@Override
public Collection<Name> getClassNames(@NotNull FqName packageName) {
return javaNamespaceResolver.getClassNamesInPackage(packageName);
}
};
@Inject
public void setAnnotationDeserializer(AnnotationDescriptorDeserializer annotationDeserializer) {
this.annotationDeserializer = annotationDeserializer;
}
@Inject
public void setJavaNamespaceResolver(JavaNamespaceResolver javaNamespaceResolver) {
this.javaNamespaceResolver = javaNamespaceResolver;
}
@Inject
public void setJavaClassResolver(JavaClassResolver javaClassResolver) {
this.javaClassResolver = javaClassResolver;
}
@Inject
public void setErrorReporter(ErrorReporter errorReporter) {
this.errorReporter = errorReporter;
}
@Nullable
public ClassDescriptor resolveClass(@NotNull ClassId id, @NotNull VirtualFile file) {
String[] data = readData(file);
if (data != null) {
ClassData classData = JavaProtoBufUtil.readClassDataFrom(data);
return createDeserializedClass(classData, id);
}
return null;
}
@Nullable
public JetScope createKotlinPackageScope(@NotNull NamespaceDescriptor descriptor, @NotNull VirtualFile file) {
String[] data = readData(file);
if (data != null) {
PackageData packageData = JavaProtoBufUtil.readPackageDataFrom(data);
return new DeserializedPackageMemberScope(storageManager, descriptor, annotationDeserializer, javaDescriptorFinder,
packageData);
}
return null;
}
@Nullable
private ClassDescriptor createDeserializedClass(@NotNull ClassData classData, @NotNull ClassId classId) {
DeclarationDescriptor owner = classId.isTopLevelClass()
? javaNamespaceResolver.resolveNamespace(classId.getPackageFqName(), INCLUDE_KOTLIN_SOURCES)
: javaClassResolver.resolveClass(kotlinFqNameToJavaFqName(classId.getOuterClassId().asSingleFqName()),
IGNORE_KOTLIN_SOURCES);
assert owner != null : "No owner found for " + classId;
return new DeserializedClassDescriptor(classId, storageManager, owner, classData.getNameResolver(),
annotationDeserializer, javaDescriptorFinder, classData.getClassProto(), null);
}
@Nullable
private String[] readData(@NotNull VirtualFile virtualFile) {
KotlinClassFileHeader header = KotlinClassFileHeader.readKotlinHeaderFromClassFile(virtualFile);
int version = header.getVersion();
if (!isAbiVersionCompatible(version) && header.getType() != KotlinClassFileHeader.HeaderType.NONE) {
errorReporter.reportIncompatibleAbiVersion(header.getFqName(), virtualFile, version);
return null;
}
return header.getAnnotationData();
}
}
@@ -1,83 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.descriptors.serialization.ClassId;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.ArrayList;
import java.util.List;
public class DeserializedResolverUtils {
private DeserializedResolverUtils() {
}
@NotNull
public static FqName kotlinFqNameToJavaFqName(@NotNull FqNameUnsafe kotlinFqName) {
List<String> correctedSegments = new ArrayList<String>();
for (Name segment : kotlinFqName.pathSegments()) {
if (segment.asString().startsWith("<class-object-for")) {
correctedSegments.add(JvmAbi.CLASS_OBJECT_CLASS_NAME);
}
else {
assert !segment.isSpecial();
correctedSegments.add(segment.asString());
}
}
return FqName.fromSegments(correctedSegments);
}
@Nullable
public static VirtualFile getVirtualFile(@NotNull ClassId id, @NotNull VirtualFile outerClassFile) {
String fileExtension = outerClassFile.getExtension();
if (!"class".equals(fileExtension)) {
return null;
}
FqNameUnsafe relativeClassName = id.getRelativeClassName();
assert relativeClassName.isSafe() : "Relative class name " + relativeClassName.asString() + " should be safe at this point";
String classNameWithBucks = relativeClassName.asString().replace(".", "$") + ".class";
VirtualFile virtualFile = outerClassFile.getParent().findChild(classNameWithBucks);
if (virtualFile == null) {
throw new IllegalStateException("No virtual file for " + id.asSingleFqName().asString());
}
return virtualFile;
}
@NotNull
public static FqNameUnsafe naiveKotlinFqName(@NotNull ClassDescriptor descriptor) {
DeclarationDescriptor containing = descriptor.getContainingDeclaration();
if (containing instanceof ClassDescriptor) {
return naiveKotlinFqName((ClassDescriptor) containing).child(descriptor.getName());
}
else if (containing instanceof NamespaceDescriptor) {
return DescriptorUtils.getFQName(containing).child(descriptor.getName());
}
else {
throw new IllegalArgumentException("Class doesn't have a FQ name: " + descriptor);
}
}
}
@@ -1,25 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.name.FqName;
public interface ErrorReporter {
void reportIncompatibleAbiVersion(@NotNull FqName fqName, @NotNull VirtualFile file, int actualVersion);
}
@@ -1,33 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.java.structure.JavaAnnotation;
import org.jetbrains.jet.lang.resolve.java.structure.JavaAnnotationOwner;
import org.jetbrains.jet.lang.resolve.name.FqName;
import java.util.Collection;
public interface ExternalAnnotationResolver {
@Nullable
JavaAnnotation findExternalAnnotation(@NotNull JavaAnnotationOwner owner, @NotNull FqName fqName);
@NotNull
Collection<JavaAnnotation> findExternalAnnotations(@NotNull JavaAnnotationOwner owner);
}
@@ -1,147 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.java.structure.JavaField;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collections;
import java.util.List;
public interface ExternalSignatureResolver {
abstract class MemberSignature {
private final List<String> signatureErrors;
protected MemberSignature(@NotNull List<String> signatureErrors) {
this.signatureErrors = signatureErrors;
}
@NotNull
public List<String> getErrors() {
return signatureErrors;
}
}
class AlternativeMethodSignature extends MemberSignature {
private final JetType returnType;
private final JetType receiverType;
private final List<ValueParameterDescriptor> valueParameters;
private final List<TypeParameterDescriptor> typeParameters;
public AlternativeMethodSignature(
@Nullable JetType returnType,
@Nullable JetType receiverType,
@NotNull List<ValueParameterDescriptor> valueParameters,
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull List<String> signatureErrors
) {
super(signatureErrors);
this.returnType = returnType;
this.receiverType = receiverType;
this.valueParameters = valueParameters;
this.typeParameters = typeParameters;
}
@Nullable
public JetType getReturnType() {
return returnType;
}
@Nullable
public JetType getReceiverType() {
return receiverType;
}
@NotNull
public List<ValueParameterDescriptor> getValueParameters() {
return valueParameters;
}
@NotNull
public List<TypeParameterDescriptor> getTypeParameters() {
return typeParameters;
}
}
class AlternativeFieldSignature extends MemberSignature {
private final JetType returnType;
public AlternativeFieldSignature(@NotNull JetType returnType, @Nullable String signatureError) {
super(signatureError == null ? Collections.<String>emptyList() : Collections.singletonList(signatureError));
this.returnType = returnType;
}
@NotNull
public JetType getReturnType() {
return returnType;
}
}
class PropagatedMethodSignature extends AlternativeMethodSignature {
private final List<FunctionDescriptor> superMethods;
public PropagatedMethodSignature(
@Nullable JetType returnType,
@Nullable JetType receiverType,
@NotNull List<ValueParameterDescriptor> valueParameters,
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull List<String> signatureErrors,
@NotNull List<FunctionDescriptor> superMethods
) {
super(returnType, receiverType, valueParameters, typeParameters, signatureErrors);
this.superMethods = superMethods;
}
@NotNull
public List<FunctionDescriptor> getSuperMethods() {
return superMethods;
}
}
@NotNull
PropagatedMethodSignature resolvePropagatedSignature(
@NotNull JavaMethod method,
@NotNull ClassDescriptor owner,
@NotNull JetType returnType,
@Nullable JetType receiverType,
@NotNull List<ValueParameterDescriptor> valueParameters,
@NotNull List<TypeParameterDescriptor> typeParameters
);
@NotNull
AlternativeMethodSignature resolveAlternativeMethodSignature(
@NotNull JavaMethod method,
boolean hasSuperMethods,
@Nullable JetType returnType,
@Nullable JetType receiverType,
@NotNull List<ValueParameterDescriptor> valueParameters,
@NotNull List<TypeParameterDescriptor> typeParameters
);
@NotNull
AlternativeFieldSignature resolveAlternativeFieldSignature(
@NotNull JavaField field,
@NotNull JetType returnType,
boolean isVar
);
void reportSignatureErrors(@NotNull CallableMemberDescriptor descriptor, @NotNull List<String> signatureErrors);
}
@@ -1,24 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
public interface FakeOverrideVisibilityResolver {
void resolveUnknownVisibilityForMember(@NotNull CallableMemberDescriptor descriptor);
}
@@ -1,183 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.constants.*;
import org.jetbrains.jet.lang.resolve.constants.StringValue;
import org.jetbrains.jet.lang.resolve.java.structure.*;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getEnumEntriesScope;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.INCLUDE_KOTLIN_SOURCES;
public final class JavaAnnotationArgumentResolver {
private JavaAnnotationResolver annotationResolver;
private JavaClassResolver classResolver;
@Inject
public void setAnnotationResolver(JavaAnnotationResolver annotationResolver) {
this.annotationResolver = annotationResolver;
}
@Inject
public void setClassResolver(JavaClassResolver classResolver) {
this.classResolver = classResolver;
}
@Nullable
public CompileTimeConstant<?> resolveAnnotationArgument(
@NotNull FqName annotationFqName,
@NotNull JavaAnnotationArgument argument,
@NotNull PostponedTasks postponedTasks
) {
if (argument instanceof JavaLiteralAnnotationArgument) {
return resolveCompileTimeConstantValue(((JavaLiteralAnnotationArgument) argument).getValue(), null);
}
// Enum
else if (argument instanceof JavaReferenceAnnotationArgument) {
return resolveFromReference(((JavaReferenceAnnotationArgument) argument).resolve(), postponedTasks);
}
// Array
else if (argument instanceof JavaArrayAnnotationArgument) {
Name argumentName = argument.getName();
return resolveFromArray(
annotationFqName,
argumentName == null ? JavaAnnotationResolver.DEFAULT_ANNOTATION_MEMBER_NAME : argumentName,
((JavaArrayAnnotationArgument) argument).getElements(),
postponedTasks
);
}
// Annotation
else if (argument instanceof JavaAnnotationAsAnnotationArgument) {
return resolveFromAnnotation(((JavaAnnotationAsAnnotationArgument) argument).getAnnotation(), postponedTasks);
}
return null;
}
@Nullable
private CompileTimeConstant<?> resolveFromAnnotation(@NotNull JavaAnnotation value, @NotNull PostponedTasks taskList) {
AnnotationDescriptor descriptor = annotationResolver.resolveAnnotation(value, taskList);
return descriptor == null ? null : new AnnotationValue(descriptor);
}
@Nullable
private CompileTimeConstant<?> resolveFromArray(
@NotNull FqName annotationFqName,
@NotNull Name argumentName,
@NotNull Collection<JavaAnnotationArgument> elements,
@NotNull PostponedTasks taskList
) {
ClassDescriptor annotationClass = classResolver.resolveClass(annotationFqName, INCLUDE_KOTLIN_SOURCES, taskList);
if (annotationClass == null) return null;
//TODO: nullability issues
ValueParameterDescriptor valueParameter = DescriptorResolverUtils.getAnnotationParameterByName(argumentName, annotationClass);
if (valueParameter == null) return null;
List<CompileTimeConstant<?>> values = new ArrayList<CompileTimeConstant<?>>(elements.size());
for (JavaAnnotationArgument argument : elements) {
CompileTimeConstant<?> value = resolveAnnotationArgument(annotationFqName, argument, taskList);
values.add(value == null ? NullValue.NULL : value);
}
return new ArrayValue(values, valueParameter.getType());
}
@Nullable
private CompileTimeConstant<?> resolveFromReference(@Nullable JavaElement element, @NotNull PostponedTasks taskList) {
if (!(element instanceof JavaField)) return null;
JavaField field = (JavaField) element;
if (!field.isEnumEntry()) return null;
FqName fqName = field.getContainingClass().getFqName();
if (fqName == null) return null;
ClassDescriptor enumClass = classResolver.resolveClass(fqName, INCLUDE_KOTLIN_SOURCES, taskList);
if (enumClass == null) return null;
for (VariableDescriptor variableDescriptor : getEnumEntriesScope(enumClass).getProperties(field.getName())) {
if (variableDescriptor.getReceiverParameter() == null) {
return new EnumValue((PropertyDescriptor) variableDescriptor);
}
}
return null;
}
@Nullable
public static CompileTimeConstant<?> resolveCompileTimeConstantValue(@Nullable Object value, @Nullable JetType expectedType) {
if (value instanceof String) {
return new StringValue((String) value);
}
else if (value instanceof Byte) {
return new ByteValue((Byte) value);
}
else if (value instanceof Short) {
return new ShortValue((Short) value);
}
else if (value instanceof Character) {
return new CharValue((Character) value);
}
else if (value instanceof Integer) {
KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
Integer integer = (Integer) value;
if (builtIns.getShortType().equals(expectedType)) {
return new ShortValue(integer.shortValue());
}
else if (builtIns.getByteType().equals(expectedType)) {
return new ByteValue(integer.byteValue());
}
else if (builtIns.getCharType().equals(expectedType)) {
return new CharValue((char) integer.intValue());
}
return new IntValue(integer);
}
else if (value instanceof Long) {
return new LongValue((Long) value);
}
else if (value instanceof Float) {
return new FloatValue((Float) value);
}
else if (value instanceof Double) {
return new DoubleValue((Double) value);
}
else if (value instanceof Boolean) {
return BooleanValue.valueOf((Boolean) value);
}
else if (value == null) {
return NullValue.NULL;
}
return null;
}
}
@@ -1,166 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap;
import org.jetbrains.jet.lang.resolve.java.structure.JavaAnnotation;
import org.jetbrains.jet.lang.resolve.java.structure.JavaAnnotationArgument;
import org.jetbrains.jet.lang.resolve.java.structure.JavaAnnotationOwner;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.INCLUDE_KOTLIN_SOURCES;
public final class JavaAnnotationResolver {
public static final Name DEFAULT_ANNOTATION_MEMBER_NAME = Name.identifier("value");
private JavaClassResolver classResolver;
private JavaAnnotationArgumentResolver argumentResolver;
private ExternalAnnotationResolver externalAnnotationResolver;
public JavaAnnotationResolver() {
}
@Inject
public void setClassResolver(JavaClassResolver classResolver) {
this.classResolver = classResolver;
}
@Inject
public void setArgumentResolver(JavaAnnotationArgumentResolver argumentResolver) {
this.argumentResolver = argumentResolver;
}
@Inject
public void setExternalAnnotationResolver(ExternalAnnotationResolver externalAnnotationResolver) {
this.externalAnnotationResolver = externalAnnotationResolver;
}
private void resolveAnnotations(
@NotNull Collection<JavaAnnotation> annotations,
@NotNull PostponedTasks tasks,
@NotNull List<AnnotationDescriptor> result
) {
for (JavaAnnotation javaAnnotation : annotations) {
AnnotationDescriptor annotation = resolveAnnotation(javaAnnotation, tasks);
if (annotation != null) {
result.add(annotation);
}
}
}
@NotNull
public List<AnnotationDescriptor> resolveAnnotations(@NotNull JavaAnnotationOwner owner, @NotNull PostponedTasks tasks) {
List<AnnotationDescriptor> result = new ArrayList<AnnotationDescriptor>();
resolveAnnotations(owner.getAnnotations(), tasks, result);
resolveAnnotations(externalAnnotationResolver.findExternalAnnotations(owner), tasks, result);
return result;
}
@NotNull
public List<AnnotationDescriptor> resolveAnnotations(@NotNull JavaAnnotationOwner owner) {
PostponedTasks postponedTasks = new PostponedTasks();
List<AnnotationDescriptor> annotations = resolveAnnotations(owner, postponedTasks);
postponedTasks.performTasks();
return annotations;
}
@Nullable
public AnnotationDescriptor resolveAnnotation(@NotNull JavaAnnotation javaAnnotation, @NotNull PostponedTasks postponedTasks) {
final AnnotationDescriptor annotation = new AnnotationDescriptor();
FqName fqName = javaAnnotation.getFqName();
if (fqName == null) {
return null;
}
// Don't process internal jet annotations and jetbrains NotNull annotations
if (fqName.asString().startsWith("jet.runtime.typeinfo.")
|| fqName.equals(JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION.getFqName())
|| fqName.equals(JvmAnnotationNames.KOTLIN_CLASS.getFqName())
|| fqName.equals(JvmAnnotationNames.KOTLIN_PACKAGE.getFqName())
) {
return null;
}
AnnotationDescriptor mappedClassDescriptor = JavaToKotlinClassMap.getInstance().mapToAnnotationClass(fqName);
if (mappedClassDescriptor != null) {
return mappedClassDescriptor;
}
final ClassDescriptor annotationClass = classResolver.resolveClass(fqName, INCLUDE_KOTLIN_SOURCES, postponedTasks);
if (annotationClass == null) {
return null;
}
postponedTasks.addTask(new Runnable() {
@Override
public void run() {
annotation.setAnnotationType(annotationClass.getDefaultType());
}
});
for (JavaAnnotationArgument argument : javaAnnotation.getArguments()) {
CompileTimeConstant value = argumentResolver.resolveAnnotationArgument(fqName, argument, postponedTasks);
if (value == null) continue;
Name name = argument.getName();
ValueParameterDescriptor descriptor = DescriptorResolverUtils.getAnnotationParameterByName(
name == null ? DEFAULT_ANNOTATION_MEMBER_NAME : name, annotationClass);
if (descriptor != null) {
annotation.setValueArgument(descriptor, value);
}
}
return annotation;
}
@Nullable
public JavaAnnotation findAnnotationWithExternal(@NotNull JavaAnnotationOwner owner, @NotNull JvmClassName name) {
JavaAnnotation annotation = owner.findAnnotation(name.getFqName());
if (annotation != null) {
return annotation;
}
return externalAnnotationResolver.findExternalAnnotation(owner, name.getFqName());
}
public boolean hasNotNullAnnotation(@NotNull JavaAnnotationOwner owner) {
return findAnnotationWithExternal(owner, JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION) != null;
}
public boolean hasMutableAnnotation(@NotNull JavaAnnotationOwner owner) {
return findAnnotationWithExternal(owner, JvmAnnotationNames.JETBRAINS_MUTABLE_ANNOTATION) != null;
}
public boolean hasReadonlyAnnotation(@NotNull JavaAnnotationOwner owner) {
return findAnnotationWithExternal(owner, JvmAnnotationNames.JETBRAINS_READONLY_ANNOTATION) != null;
}
}
@@ -1,480 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.descriptors.serialization.ClassId;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule;
import org.jetbrains.jet.lang.resolve.java.JavaClassFinder;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils;
import org.jetbrains.jet.lang.resolve.java.scope.JavaClassNonStaticMembersScope;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
import org.jetbrains.jet.lang.resolve.java.vfilefinder.VirtualFileFinder;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import javax.inject.Inject;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassObjectName;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.INCLUDE_KOTLIN_SOURCES;
public final class JavaClassResolver {
private static final Logger LOG = Logger.getInstance(JavaClassResolver.class);
@NotNull
private final Map<FqNameUnsafe, ClassDescriptor> classDescriptorCache = new HashMap<FqNameUnsafe, ClassDescriptor>();
@NotNull
private final Set<FqNameUnsafe> unresolvedCache = new HashSet<FqNameUnsafe>();
private JavaResolverCache cache;
private JavaTypeParameterResolver typeParameterResolver;
private JavaMemberResolver memberResolver;
private JavaAnnotationResolver annotationResolver;
private JavaClassFinder javaClassFinder;
private JavaNamespaceResolver namespaceResolver;
private JavaSupertypeResolver supertypesResolver;
private JavaFunctionResolver functionResolver;
private DeserializedDescriptorResolver deserializedDescriptorResolver;
private VirtualFileFinder virtualFileFinder;
public JavaClassResolver() {
}
@Inject
public void setVirtualFileFinder(VirtualFileFinder virtualFileFinder) {
this.virtualFileFinder = virtualFileFinder;
}
@Inject
public void setCache(JavaResolverCache cache) {
this.cache = cache;
}
@Inject
public void setDeserializedDescriptorResolver(DeserializedDescriptorResolver deserializedDescriptorResolver) {
this.deserializedDescriptorResolver = deserializedDescriptorResolver;
}
@Inject
public void setTypeParameterResolver(JavaTypeParameterResolver typeParameterResolver) {
this.typeParameterResolver = typeParameterResolver;
}
@Inject
public void setMemberResolver(JavaMemberResolver memberResolver) {
this.memberResolver = memberResolver;
}
@Inject
public void setAnnotationResolver(JavaAnnotationResolver annotationResolver) {
this.annotationResolver = annotationResolver;
}
@Inject
public void setJavaClassFinder(JavaClassFinder javaClassFinder) {
this.javaClassFinder = javaClassFinder;
}
@Inject
public void setNamespaceResolver(JavaNamespaceResolver namespaceResolver) {
this.namespaceResolver = namespaceResolver;
}
@Inject
public void setSupertypesResolver(JavaSupertypeResolver supertypesResolver) {
this.supertypesResolver = supertypesResolver;
}
@Inject
public void setFunctionResolver(JavaFunctionResolver functionResolver) {
this.functionResolver = functionResolver;
}
@Nullable
public ClassDescriptor resolveClass(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule) {
PostponedTasks postponedTasks = new PostponedTasks();
ClassDescriptor classDescriptor = resolveClass(qualifiedName, searchRule, postponedTasks);
postponedTasks.performTasks();
return classDescriptor;
}
@Nullable
public ClassDescriptor resolveClass(
@NotNull FqName qualifiedName,
@NotNull DescriptorSearchRule searchRule,
@NotNull PostponedTasks tasks
) {
if (isTraitImplementation(qualifiedName)) {
return null;
}
ClassDescriptor builtinClassDescriptor = getKotlinBuiltinClassDescriptor(qualifiedName);
if (builtinClassDescriptor != null) {
return builtinClassDescriptor;
}
ClassDescriptor kotlinClassDescriptor = cache.getClassResolvedFromSource(qualifiedName);
if (kotlinClassDescriptor != null) {
return searchRule.processFoundInKotlin(kotlinClassDescriptor);
}
FqNameUnsafe fqName = javaClassToKotlinFqName(qualifiedName);
ClassDescriptor cachedDescriptor = classDescriptorCache.get(fqName);
if (cachedDescriptor != null) {
return cachedDescriptor;
}
if (unresolvedCache.contains(fqName)) {
return null;
}
return doResolveClass(qualifiedName, tasks);
}
@Nullable
private static ClassDescriptor getKotlinBuiltinClassDescriptor(@NotNull FqName qualifiedName) {
if (!qualifiedName.firstSegmentIs(KotlinBuiltIns.BUILT_INS_PACKAGE_NAME)) return null;
List<Name> segments = qualifiedName.pathSegments();
if (segments.size() < 2) return null;
JetScope scope = KotlinBuiltIns.getInstance().getBuiltInsScope();
for (int i = 1, size = segments.size(); i < size; i++) {
ClassifierDescriptor classifier = scope.getClassifier(segments.get(i));
if (classifier == null) return null;
assert classifier instanceof ClassDescriptor : "Unexpected classifier in built-ins: " + classifier;
scope = ((ClassDescriptor) classifier).getUnsubstitutedInnerClassesScope();
}
return (ClassDescriptor) scope.getContainingDeclaration();
}
private ClassDescriptor doResolveClass(@NotNull FqName qualifiedName, @NotNull PostponedTasks tasks) {
//TODO: correct scope
VirtualFile file = virtualFileFinder.find(qualifiedName);
if (file != null) {
//TODO: code duplication
//TODO: it is a hackish way to determine whether it is inner class or not
boolean isInnerClass = file.getName().contains("$");
ClassOrNamespaceDescriptor containingDeclaration = resolveParentDescriptor(qualifiedName, isInnerClass);
// class may be resolved during resolution of parent
ClassDescriptor cachedDescriptor = classDescriptorCache.get(javaClassToKotlinFqName(qualifiedName));
if (cachedDescriptor != null) {
return cachedDescriptor;
}
assert !unresolvedCache.contains(qualifiedName.toUnsafe())
: "We can resolve the class, so it can't be 'unresolved' during parent resolution";
ClassId id = ClassId.fromFqNameAndContainingDeclaration(qualifiedName, containingDeclaration);
ClassDescriptor deserializedDescriptor = deserializedDescriptorResolver.resolveClass(id, file);
if (deserializedDescriptor != null) {
cache(javaClassToKotlinFqName(qualifiedName), deserializedDescriptor);
return deserializedDescriptor;
}
}
JavaClass javaClass = javaClassFinder.findClass(qualifiedName);
if (javaClass == null) {
cacheNegativeValue(javaClassToKotlinFqName(qualifiedName));
return null;
}
if (KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME.equals(qualifiedName.parent())) {
if (javaClass.findAnnotation(JvmAnnotationNames.ASSERT_INVISIBLE_IN_RESOLVER.getFqName()) != null) {
if (ApplicationManager.getApplication().isInternal()) {
LOG.error("classpath is configured incorrectly:" +
" class " + qualifiedName + " from runtime must not be loaded by compiler");
}
return null;
}
}
// Class may have been resolved previously by different Java resolver instance, and we are reusing its trace
ClassDescriptor alreadyResolved = cache.getClass(javaClass);
if (alreadyResolved != null) {
return alreadyResolved;
}
//TODO: code duplication
ClassOrNamespaceDescriptor containingDeclaration = resolveParentDescriptor(qualifiedName, javaClass.getOuterClass() != null);
// class may be resolved during resolution of parent
ClassDescriptor cachedDescriptor = classDescriptorCache.get(javaClassToKotlinFqName(qualifiedName));
if (cachedDescriptor != null) {
return cachedDescriptor;
}
assert !unresolvedCache.contains(qualifiedName.toUnsafe())
: "We can resolve the class, so it can't be 'unresolved' during parent resolution";
checkFqNamesAreConsistent(javaClass, qualifiedName);
assert javaClass.getOriginKind() != JavaClass.OriginKind.KOTLIN_LIGHT_CLASS :
"Trying to resolve a light class as a regular PsiClass: " + javaClass.getFqName();
return doCreateClassDescriptor(qualifiedName, javaClass, tasks, containingDeclaration);
}
private void cacheNegativeValue(@NotNull FqNameUnsafe fqNameUnsafe) {
if (unresolvedCache.contains(fqNameUnsafe) || classDescriptorCache.containsKey(fqNameUnsafe)) {
throw new IllegalStateException("rewrite at " + fqNameUnsafe);
}
unresolvedCache.add(fqNameUnsafe);
}
private static boolean isTraitImplementation(@NotNull FqName qualifiedName) {
// TODO: only if -$$TImpl class is created by Kotlin
return qualifiedName.asString().endsWith(JvmAbi.TRAIT_IMPL_SUFFIX);
}
@NotNull
private ClassDescriptorFromJvmBytecode doCreateClassDescriptor(
@NotNull FqName fqName,
@NotNull JavaClass javaClass,
@NotNull PostponedTasks taskList,
@NotNull ClassOrNamespaceDescriptor containingDeclaration
) {
ClassDescriptorFromJvmBytecode classDescriptor =
new ClassDescriptorFromJvmBytecode(containingDeclaration, determineClassKind(javaClass), isInnerClass(javaClass));
cache(javaClassToKotlinFqName(fqName), classDescriptor);
classDescriptor.setName(javaClass.getName());
JavaTypeParameterResolver.Initializer typeParameterInitializer = typeParameterResolver.resolveTypeParameters(classDescriptor, javaClass);
classDescriptor.setTypeParameterDescriptors(typeParameterInitializer.getDescriptors());
List<JetType> supertypes = new ArrayList<JetType>();
classDescriptor.setSupertypes(supertypes);
classDescriptor.setVisibility(javaClass.getVisibility());
classDescriptor.setModality(determineClassModality(javaClass));
classDescriptor.createTypeConstructor();
JavaClassNonStaticMembersScope scope = new JavaClassNonStaticMembersScope(classDescriptor, javaClass, false, memberResolver);
classDescriptor.setScopeForMemberLookup(scope);
classDescriptor.setScopeForConstructorResolve(scope);
typeParameterInitializer.initialize();
// TODO: ugly hack: tests crash if initializeTypeParameters called with class containing proper supertypes
List<TypeParameterDescriptor> classTypeParameters = classDescriptor.getTypeConstructor().getParameters();
supertypes.addAll(supertypesResolver.getSupertypes(classDescriptor, javaClass, classTypeParameters));
if (javaClass.isEnum()) {
ClassDescriptorFromJvmBytecode classObjectDescriptor = createClassObjectDescriptorForEnum(classDescriptor, javaClass);
cache(getFqNameForClassObject(javaClass), classObjectDescriptor);
classDescriptor.getBuilder().setClassObjectDescriptor(classObjectDescriptor);
}
classDescriptor.setAnnotations(annotationResolver.resolveAnnotations(javaClass, taskList));
cache.recordClass(javaClass, classDescriptor);
JavaMethod samInterfaceMethod = SingleAbstractMethodUtils.getSamInterfaceMethod(javaClass);
if (samInterfaceMethod != null) {
SimpleFunctionDescriptor abstractMethod = resolveFunctionOfSamInterface(samInterfaceMethod, classDescriptor);
classDescriptor.setFunctionTypeForSamInterface(SingleAbstractMethodUtils.getFunctionTypeForAbstractMethod(abstractMethod));
}
return classDescriptor;
}
@NotNull
private static ClassKind determineClassKind(@NotNull JavaClass klass) {
if (klass.isInterface()) {
return klass.isAnnotationType() ? ClassKind.ANNOTATION_CLASS : ClassKind.TRAIT;
}
return klass.isEnum() ? ClassKind.ENUM_CLASS : ClassKind.CLASS;
}
@NotNull
private static Modality determineClassModality(@NotNull JavaClass klass) {
return klass.isAnnotationType()
? Modality.FINAL
: Modality.convertFromFlags(klass.isAbstract() || klass.isInterface(), !klass.isFinal());
}
@NotNull
private static FqNameUnsafe getFqNameForClassObject(@NotNull JavaClass javaClass) {
FqName fqName = javaClass.getFqName();
assert fqName != null : "Reading java class with no qualified name";
return fqName.toUnsafe().child(getClassObjectName(javaClass.getName()));
}
@NotNull
private SimpleFunctionDescriptor resolveFunctionOfSamInterface(
@NotNull JavaMethod samInterfaceMethod,
@NotNull ClassDescriptorFromJvmBytecode samInterface
) {
JavaClass methodContainer = samInterfaceMethod.getContainingClass();
FqName containerFqName = methodContainer.getFqName();
assert containerFqName != null : "qualified name is null for " + methodContainer;
if (DescriptorUtils.getFQName(samInterface).equalsTo(containerFqName)) {
SimpleFunctionDescriptor abstractMethod = functionResolver.resolveFunctionMutely(samInterfaceMethod, samInterface);
assert abstractMethod != null : "couldn't resolve method " + samInterfaceMethod;
return abstractMethod;
}
else {
return findFunctionWithMostSpecificReturnType(TypeUtils.getAllSupertypes(samInterface.getDefaultType()));
}
}
@NotNull
private static SimpleFunctionDescriptor findFunctionWithMostSpecificReturnType(@NotNull Set<JetType> supertypes) {
List<SimpleFunctionDescriptor> candidates = new ArrayList<SimpleFunctionDescriptor>(supertypes.size());
for (JetType supertype : supertypes) {
List<CallableMemberDescriptor> abstractMembers = SingleAbstractMethodUtils.getAbstractMembers(supertype);
if (!abstractMembers.isEmpty()) {
candidates.add((SimpleFunctionDescriptor) abstractMembers.get(0));
}
}
if (candidates.isEmpty()) {
throw new IllegalStateException("Couldn't find abstract method in supertypes " + supertypes);
}
SimpleFunctionDescriptor currentMostSpecificType = candidates.get(0);
for (SimpleFunctionDescriptor candidate : candidates) {
JetType candidateReturnType = candidate.getReturnType();
JetType currentMostSpecificReturnType = currentMostSpecificType.getReturnType();
assert candidateReturnType != null && currentMostSpecificReturnType != null : candidate + ", " + currentMostSpecificReturnType;
if (JetTypeChecker.INSTANCE.isSubtypeOf(candidateReturnType, currentMostSpecificReturnType)) {
currentMostSpecificType = candidate;
}
}
return currentMostSpecificType;
}
private void cache(@NotNull FqNameUnsafe fqName, @Nullable ClassDescriptor classDescriptor) {
if (classDescriptor == null) {
cacheNegativeValue(fqName);
}
else {
ClassDescriptor oldValue = classDescriptorCache.put(fqName, classDescriptor);
assert oldValue == null;
}
}
private void checkFqNamesAreConsistent(@NotNull JavaClass javaClass, @NotNull FqName desiredFqName) {
FqName fqName = javaClass.getFqName();
assert desiredFqName.equals(fqName) : "Inconsistent FQ names: " + fqName + ", " + desiredFqName;
FqNameUnsafe correctedName = javaClassToKotlinFqName(fqName);
if (classDescriptorCache.containsKey(correctedName) || unresolvedCache.contains(correctedName)) {
throw new IllegalStateException("Cache already contains FQ name: " + fqName.asString());
}
}
@NotNull
private ClassOrNamespaceDescriptor resolveParentDescriptor(@NotNull FqName childClassFQName, boolean isInnerClass) {
FqName parentFqName = childClassFQName.parent();
if (isInnerClass) {
ClassDescriptor parentClass = resolveClass(parentFqName, INCLUDE_KOTLIN_SOURCES);
if (parentClass == null) {
throw new IllegalStateException("Could not resolve " + parentFqName + " required to be parent for " + childClassFQName);
}
return parentClass;
}
else {
NamespaceDescriptor parentNamespace = namespaceResolver.resolveNamespace(parentFqName, INCLUDE_KOTLIN_SOURCES);
if (parentNamespace == null) {
throw new IllegalStateException("Could not resolve " + parentFqName + " required to be parent for " + childClassFQName);
}
return parentNamespace;
}
}
// This method replaces "object" segments of FQ name to "<class-object-for-...>"
@NotNull
private static FqNameUnsafe javaClassToKotlinFqName(@NotNull FqName rawFqName) {
List<Name> correctedSegments = new ArrayList<Name>();
for (Name segment : rawFqName.pathSegments()) {
if (JvmAbi.CLASS_OBJECT_CLASS_NAME.equals(segment.asString())) {
assert !correctedSegments.isEmpty();
Name previous = correctedSegments.get(correctedSegments.size() - 1);
correctedSegments.add(DescriptorUtils.getClassObjectName(previous));
}
else {
correctedSegments.add(segment);
}
}
return FqNameUnsafe.fromSegments(correctedSegments);
}
private static boolean isInnerClass(@NotNull JavaClass javaClass) {
return javaClass.getOuterClass() != null && !javaClass.isStatic();
}
@NotNull
private ClassDescriptorFromJvmBytecode createClassObjectDescriptorForEnum(
@NotNull ClassDescriptor containing,
@NotNull JavaClass javaClass
) {
ClassDescriptorFromJvmBytecode classObjectDescriptor = createSyntheticClassObject(containing, javaClass);
JetType valuesReturnType = KotlinBuiltIns.getInstance().getArrayType(containing.getDefaultType());
SimpleFunctionDescriptor valuesMethod =
DescriptorResolver.createEnumClassObjectValuesMethod(classObjectDescriptor, valuesReturnType);
classObjectDescriptor.getBuilder().addFunctionDescriptor(valuesMethod);
JetType valueOfReturnType = containing.getDefaultType();
SimpleFunctionDescriptor valueOfMethod =
DescriptorResolver.createEnumClassObjectValueOfMethod(classObjectDescriptor, valueOfReturnType);
classObjectDescriptor.getBuilder().addFunctionDescriptor(valueOfMethod);
return classObjectDescriptor;
}
@NotNull
private ClassDescriptorFromJvmBytecode createSyntheticClassObject(@NotNull ClassDescriptor containing, @NotNull JavaClass javaClass) {
ClassDescriptorFromJvmBytecode classObjectDescriptor =
new ClassDescriptorFromJvmBytecode(containing, ClassKind.CLASS_OBJECT, false);
classObjectDescriptor.setName(getClassObjectName(containing.getName()));
classObjectDescriptor.setModality(Modality.FINAL);
classObjectDescriptor.setVisibility(containing.getVisibility());
classObjectDescriptor.setTypeParameterDescriptors(Collections.<TypeParameterDescriptor>emptyList());
classObjectDescriptor.createTypeConstructor();
JavaClassNonStaticMembersScope scope = new JavaClassNonStaticMembersScope(classObjectDescriptor, javaClass, true, memberResolver);
WritableScopeImpl writableScope =
new WritableScopeImpl(scope, classObjectDescriptor, RedeclarationHandler.THROW_EXCEPTION, "Member lookup scope");
writableScope.changeLockLevel(WritableScope.LockLevel.BOTH);
classObjectDescriptor.setScopeForMemberLookup(writableScope);
classObjectDescriptor.setScopeForConstructorResolve(scope);
return classObjectDescriptor;
}
}
@@ -1,229 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
import org.jetbrains.jet.lang.resolve.java.JavaVisibilities;
import org.jetbrains.jet.lang.resolve.java.descriptor.SamAdapterDescriptor;
import org.jetbrains.jet.lang.resolve.java.structure.JavaArrayType;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
import org.jetbrains.jet.lang.resolve.java.structure.JavaType;
import org.jetbrains.jet.lang.types.JetType;
import javax.inject.Inject;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils.createSamAdapterConstructor;
import static org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils.isSamAdapterNecessary;
public final class JavaConstructorResolver {
private JavaResolverCache cache;
private JavaTypeTransformer typeTransformer;
private JavaValueParameterResolver valueParameterResolver;
private ExternalSignatureResolver externalSignatureResolver;
public JavaConstructorResolver() {
}
@Inject
public void setCache(JavaResolverCache cache) {
this.cache = cache;
}
@Inject
public void setTypeTransformer(JavaTypeTransformer typeTransformer) {
this.typeTransformer = typeTransformer;
}
@Inject
public void setValueParameterResolver(JavaValueParameterResolver valueParameterResolver) {
this.valueParameterResolver = valueParameterResolver;
}
@Inject
public void setExternalSignatureResolver(ExternalSignatureResolver externalSignatureResolver) {
this.externalSignatureResolver = externalSignatureResolver;
}
@NotNull
public Collection<ConstructorDescriptor> resolveConstructors(@NotNull JavaClass javaClass, @NotNull ClassDescriptor containingClass) {
Collection<ConstructorDescriptor> result = new ArrayList<ConstructorDescriptor>();
Collection<JavaMethod> constructors = javaClass.getConstructors();
if (containingClass.getKind() == ClassKind.OBJECT || containingClass.getKind() == ClassKind.CLASS_OBJECT) {
result.add(DescriptorResolver.createPrimaryConstructorForObject(containingClass));
}
else if (constructors.isEmpty()) {
ConstructorDescriptor defaultConstructor = resolveDefaultConstructor(javaClass, containingClass);
if (defaultConstructor != null) {
result.add(defaultConstructor);
}
}
else {
for (JavaMethod constructor : constructors) {
ConstructorDescriptor descriptor = resolveConstructor(constructor, containingClass, javaClass.isStatic());
result.add(descriptor);
ConstructorDescriptor samAdapter = resolveSamAdapter(descriptor);
if (samAdapter != null) {
result.add(samAdapter);
}
}
}
for (ConstructorDescriptor constructor : result) {
((ConstructorDescriptorImpl) constructor).setReturnType(containingClass.getDefaultType());
}
return result;
}
@Nullable
private ConstructorDescriptor resolveDefaultConstructor(@NotNull JavaClass javaClass, @NotNull ClassDescriptor containingClass) {
ConstructorDescriptor alreadyResolved = cache.getConstructor(javaClass);
if (alreadyResolved != null) {
return alreadyResolved;
}
boolean isAnnotation = javaClass.isAnnotationType();
if (javaClass.isInterface() && !isAnnotation) return null;
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(
containingClass,
Collections.<AnnotationDescriptor>emptyList(),
true);
List<TypeParameterDescriptor> typeParameters = containingClass.getTypeConstructor().getParameters();
List<ValueParameterDescriptor> valueParameters;
if (isAnnotation) {
TypeVariableResolver typeVariableResolver = new TypeVariableResolver(typeParameters, containingClass);
valueParameters = resolveAnnotationParameters(javaClass, constructorDescriptor, typeVariableResolver);
}
else {
valueParameters = Collections.emptyList();
}
constructorDescriptor.initialize(typeParameters, valueParameters, getConstructorVisibility(containingClass), javaClass.isStatic());
cache.recordConstructor(javaClass, constructorDescriptor);
return constructorDescriptor;
}
@NotNull
private List<ValueParameterDescriptor> resolveAnnotationParameters(
@NotNull JavaClass javaClass,
@NotNull ConstructorDescriptor constructorDescriptor,
@NotNull TypeVariableResolver typeVariableResolver
) {
// A constructor for an annotation type takes all the "methods" in the @interface as parameters
Collection<JavaMethod> methods = javaClass.getMethods();
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(methods.size());
int index = 0;
for (Iterator<JavaMethod> iterator = methods.iterator(); iterator.hasNext(); ) {
JavaMethod method = iterator.next();
assert method.getValueParameters().isEmpty() : "Annotation method can't have parameters: " + method;
JavaType returnType = method.getReturnType();
assert returnType != null : "Annotation method has no return type: " + method;
// We take the following heuristic convention:
// if the last method of the @interface is an array, we convert it into a vararg
JetType varargElementType = null;
if (!iterator.hasNext() && returnType instanceof JavaArrayType) {
JavaType componentType = ((JavaArrayType) returnType).getComponentType();
varargElementType = typeTransformer.transformToType(componentType, typeVariableResolver);
}
result.add(new ValueParameterDescriptorImpl(
constructorDescriptor,
index,
Collections.<AnnotationDescriptor>emptyList(),
method.getName(),
typeTransformer.transformToType(returnType, typeVariableResolver),
method.hasAnnotationParameterDefaultValue(),
varargElementType));
index++;
}
return result;
}
@NotNull
private static Visibility getConstructorVisibility(@NotNull ClassDescriptor classDescriptor) {
Visibility visibility = classDescriptor.getVisibility();
if (visibility == JavaVisibilities.PROTECTED_STATIC_VISIBILITY) {
return JavaVisibilities.PROTECTED_AND_PACKAGE;
}
return visibility;
}
@NotNull
private ConstructorDescriptor resolveConstructor(
@NotNull JavaMethod constructor,
@NotNull ClassDescriptor classDescriptor,
boolean isStaticClass
) {
ConstructorDescriptor alreadyResolved = cache.getConstructor(constructor);
if (alreadyResolved != null) {
return alreadyResolved;
}
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(
classDescriptor,
Collections.<AnnotationDescriptor>emptyList(), // TODO
false);
List<TypeParameterDescriptor> typeParameters = classDescriptor.getTypeConstructor().getParameters();
List<ValueParameterDescriptor> valueParameters = valueParameterResolver.resolveValueParameters(
constructorDescriptor, constructor,
new TypeVariableResolver(typeParameters, classDescriptor)
);
ExternalSignatureResolver.AlternativeMethodSignature effectiveSignature = externalSignatureResolver
.resolveAlternativeMethodSignature(constructor, false, null, null, valueParameters,
Collections.<TypeParameterDescriptor>emptyList());
constructorDescriptor
.initialize(typeParameters, effectiveSignature.getValueParameters(), constructor.getVisibility(), isStaticClass);
List<String> signatureErrors = effectiveSignature.getErrors();
if (!signatureErrors.isEmpty()) {
externalSignatureResolver.reportSignatureErrors(constructorDescriptor, signatureErrors);
}
cache.recordConstructor(constructor, constructorDescriptor);
return constructorDescriptor;
}
@Nullable
private static ConstructorDescriptor resolveSamAdapter(@NotNull ConstructorDescriptor original) {
return isSamAdapterNecessary(original) ? (ConstructorDescriptor) createSamAdapterConstructor(original) : null;
}
}
@@ -1,315 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorParent;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
import org.jetbrains.jet.lang.resolve.java.descriptor.JavaMethodDescriptor;
import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptor;
import org.jetbrains.jet.lang.resolve.java.scope.NamedMembers;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
import org.jetbrains.jet.lang.resolve.java.structure.JavaType;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import javax.inject.Inject;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
import static org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils.resolveOverrides;
import static org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils.*;
public final class JavaFunctionResolver {
private JavaTypeTransformer typeTransformer;
private JavaResolverCache cache;
private JavaTypeParameterResolver typeParameterResolver;
private JavaValueParameterResolver valueParameterResolver;
private JavaAnnotationResolver annotationResolver;
private ExternalSignatureResolver externalSignatureResolver;
private FakeOverrideVisibilityResolver fakeOverrideVisibilityResolver;
private MethodSignatureChecker signatureChecker;
@Inject
public void setTypeTransformer(JavaTypeTransformer typeTransformer) {
this.typeTransformer = typeTransformer;
}
@Inject
public void setCache(JavaResolverCache cache) {
this.cache = cache;
}
@Inject
public void setTypeParameterResolver(JavaTypeParameterResolver typeParameterResolver) {
this.typeParameterResolver = typeParameterResolver;
}
@Inject
public void setValueParameterResolver(JavaValueParameterResolver valueParameterResolver) {
this.valueParameterResolver = valueParameterResolver;
}
@Inject
public void setAnnotationResolver(JavaAnnotationResolver annotationResolver) {
this.annotationResolver = annotationResolver;
}
@Inject
public void setExternalSignatureResolver(ExternalSignatureResolver externalSignatureResolver) {
this.externalSignatureResolver = externalSignatureResolver;
}
@Inject
public void setFakeOverrideVisibilityResolver(FakeOverrideVisibilityResolver fakeOverrideVisibilityResolver) {
this.fakeOverrideVisibilityResolver = fakeOverrideVisibilityResolver;
}
@Inject
public void setSignatureChecker(MethodSignatureChecker signatureChecker) {
this.signatureChecker = signatureChecker;
}
@Nullable
SimpleFunctionDescriptor resolveFunctionMutely(@NotNull JavaMethod method, @NotNull ClassOrNamespaceDescriptor owner) {
return resolveMethodToFunctionDescriptor(method, owner, false);
}
@Nullable
private SimpleFunctionDescriptor resolveMethodToFunctionDescriptor(
@NotNull JavaMethod method,
@NotNull ClassOrNamespaceDescriptor ownerDescriptor,
boolean record
) {
if (!DescriptorResolverUtils.isCorrectOwnerForEnumMember(ownerDescriptor, method)) {
return null;
}
JavaType returnJavaType = method.getReturnType();
if (returnJavaType == null) {
// This means that the method is a constructor
return null;
}
SimpleFunctionDescriptor alreadyResolved = cache.getMethod(method);
if (alreadyResolved != null) {
return alreadyResolved;
}
SimpleFunctionDescriptorImpl functionDescriptorImpl = new JavaMethodDescriptor(
ownerDescriptor,
annotationResolver.resolveAnnotations(method),
method.getName()
);
JavaTypeParameterResolver.Initializer typeParameterInitializer = typeParameterResolver.resolveTypeParameters(functionDescriptorImpl, method);
typeParameterInitializer.initialize();
List<TypeParameterDescriptor> methodTypeParameters = typeParameterInitializer.getDescriptors();
TypeVariableResolver typeVariableResolver = new TypeVariableResolver(methodTypeParameters, functionDescriptorImpl);
List<ValueParameterDescriptor> valueParameters =
valueParameterResolver.resolveValueParameters(functionDescriptorImpl, method, typeVariableResolver);
JetType returnType = makeReturnType(returnJavaType, method, typeVariableResolver);
List<String> signatureErrors;
List<FunctionDescriptor> superFunctions;
ExternalSignatureResolver.AlternativeMethodSignature effectiveSignature;
if (ownerDescriptor instanceof NamespaceDescriptor) {
superFunctions = Collections.emptyList();
effectiveSignature = externalSignatureResolver
.resolveAlternativeMethodSignature(method, false, returnType, null, valueParameters, methodTypeParameters);
signatureErrors = effectiveSignature.getErrors();
}
else if (ownerDescriptor instanceof ClassDescriptor) {
ExternalSignatureResolver.PropagatedMethodSignature propagated = externalSignatureResolver
.resolvePropagatedSignature(method, (ClassDescriptor) ownerDescriptor, returnType, null, valueParameters,
methodTypeParameters);
superFunctions = propagated.getSuperMethods();
effectiveSignature = externalSignatureResolver
.resolveAlternativeMethodSignature(method, !superFunctions.isEmpty(), propagated.getReturnType(),
propagated.getReceiverType(), propagated.getValueParameters(),
propagated.getTypeParameters());
signatureErrors = new ArrayList<String>(propagated.getErrors());
signatureErrors.addAll(effectiveSignature.getErrors());
}
else {
throw new IllegalStateException("Unknown class or namespace descriptor: " + ownerDescriptor);
}
functionDescriptorImpl.initialize(
effectiveSignature.getReceiverType(),
DescriptorUtils.getExpectedThisObjectIfNeeded(ownerDescriptor),
effectiveSignature.getTypeParameters(),
effectiveSignature.getValueParameters(),
effectiveSignature.getReturnType(),
Modality.convertFromFlags(method.isAbstract(), !method.isFinal()),
method.getVisibility(),
/*isInline = */ false
);
if (record) {
cache.recordMethod(method, functionDescriptorImpl);
}
signatureChecker.checkSignature(method, record, functionDescriptorImpl, signatureErrors, superFunctions);
return functionDescriptorImpl;
}
@NotNull
public Set<FunctionDescriptor> resolveFunctionGroupForClass(@NotNull NamedMembers members, @NotNull ClassOrNamespaceDescriptor owner) {
Name methodName = members.getName();
Set<SimpleFunctionDescriptor> functionsFromCurrent = new HashSet<SimpleFunctionDescriptor>();
for (JavaMethod method : members.getMethods()) {
SimpleFunctionDescriptor function = resolveMethodToFunctionDescriptor(method, owner, true);
if (function != null) {
functionsFromCurrent.add(function);
SimpleFunctionDescriptor samAdapter = resolveSamAdapter(function);
if (samAdapter != null) {
functionsFromCurrent.add(samAdapter);
}
}
}
if (owner instanceof NamespaceDescriptor) {
SamConstructorDescriptor samConstructor = resolveSamConstructor((NamespaceDescriptor) owner, members);
if (samConstructor != null) {
functionsFromCurrent.add(samConstructor);
}
}
Set<FunctionDescriptor> functions = new HashSet<FunctionDescriptor>();
if (owner instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) owner;
Collection<SimpleFunctionDescriptor> functionsFromSupertypes = getFunctionsFromSupertypes(methodName, classDescriptor);
functions.addAll(resolveOverrides(methodName, functionsFromSupertypes, functionsFromCurrent, classDescriptor,
fakeOverrideVisibilityResolver));
}
if (isEnumClassObject(owner)) {
for (FunctionDescriptor functionDescriptor : functionsFromCurrent) {
if (!(isEnumValueOfMethod(functionDescriptor) || isEnumValuesMethod(functionDescriptor))) {
functions.add(functionDescriptor);
}
}
}
else {
functions.addAll(functionsFromCurrent);
}
return functions;
}
@Nullable
private static ClassDescriptorFromJvmBytecode findClassInScope(@NotNull JetScope memberScope, @NotNull Name name) {
ClassifierDescriptor classifier = memberScope.getClassifier(name);
if (classifier instanceof ClassDescriptorFromJvmBytecode) {
return (ClassDescriptorFromJvmBytecode) classifier;
}
return null;
}
// E.g. we have foo.Bar.Baz class declared in Java. It will produce the following descriptors structure:
// namespace foo
// +-- class Bar
// | +-- class Baz
// +-- namespace Bar
// We need to find class 'Baz' in namespace 'foo.Bar'.
@Nullable
private static ClassDescriptorFromJvmBytecode findClassInNamespace(@NotNull NamespaceDescriptor namespace, @NotNull Name name) {
// First, try to find in namespace directly
ClassDescriptorFromJvmBytecode found = findClassInScope(namespace.getMemberScope(), name);
if (found != null) {
return found;
}
// If unsuccessful, try to find class of the same name as current (class 'foo.Bar')
NamespaceDescriptorParent parent = namespace.getContainingDeclaration();
if (parent instanceof NamespaceDescriptor) {
// Calling recursively, looking for 'Bar' in 'foo'
ClassDescriptor classForCurrentNamespace = findClassInNamespace((NamespaceDescriptor) parent, namespace.getName());
if (classForCurrentNamespace == null) {
return null;
}
// Try to find nested class 'Baz' in class 'foo.Bar'
return findClassInScope(DescriptorUtils.getStaticNestedClassesScope(classForCurrentNamespace), name);
}
return null;
}
@Nullable
public static SamConstructorDescriptor resolveSamConstructor(@NotNull NamespaceDescriptor owner, @NotNull NamedMembers namedMembers) {
if (namedMembers.getSamInterface() != null) {
ClassDescriptorFromJvmBytecode klass = findClassInNamespace(owner, namedMembers.getName());
if (klass != null) {
return createSamConstructorFunction(owner, klass);
}
}
return null;
}
@Nullable
private static SimpleFunctionDescriptor resolveSamAdapter(@NotNull SimpleFunctionDescriptor original) {
return isSamAdapterNecessary(original) ? (SimpleFunctionDescriptor) createSamAdapterFunction(original) : null;
}
@NotNull
private JetType makeReturnType(
@NotNull JavaType returnType,
@NotNull JavaMethod method,
@NotNull TypeVariableResolver typeVariableResolver
) {
TypeUsage typeUsage = annotationResolver.hasReadonlyAnnotation(method) && !annotationResolver.hasMutableAnnotation(method)
? TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT
: TypeUsage.MEMBER_SIGNATURE_COVARIANT;
JetType transformedType = typeTransformer.transformToType(returnType, typeUsage, typeVariableResolver);
if (annotationResolver.hasNotNullAnnotation(method)) {
return TypeUtils.makeNotNullable(transformedType);
}
else {
return transformedType;
}
}
@NotNull
private static Set<SimpleFunctionDescriptor> getFunctionsFromSupertypes(@NotNull Name name, @NotNull ClassDescriptor descriptor) {
Set<SimpleFunctionDescriptor> result = new LinkedHashSet<SimpleFunctionDescriptor>();
for (JetType supertype : descriptor.getTypeConstructor().getSupertypes()) {
for (FunctionDescriptor function : supertype.getMemberScope().getFunctions(name)) {
result.add((SimpleFunctionDescriptor) function);
}
}
return result;
}
}
@@ -1,87 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule;
import org.jetbrains.jet.lang.resolve.java.scope.NamedMembers;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.name.FqName;
import javax.inject.Inject;
import java.util.Collection;
import java.util.Set;
public class JavaMemberResolver {
private JavaClassResolver classResolver;
private JavaNamespaceResolver namespaceResolver;
private JavaFunctionResolver functionResolver;
private JavaPropertyResolver propertyResolver;
private JavaConstructorResolver constructorResolver;
@Inject
public void setClassResolver(JavaClassResolver classResolver) {
this.classResolver = classResolver;
}
@Inject
public void setNamespaceResolver(JavaNamespaceResolver namespaceResolver) {
this.namespaceResolver = namespaceResolver;
}
@Inject
public void setFunctionResolver(JavaFunctionResolver functionResolver) {
this.functionResolver = functionResolver;
}
@Inject
public void setPropertyResolver(JavaPropertyResolver propertyResolver) {
this.propertyResolver = propertyResolver;
}
@Inject
public void setConstructorResolver(JavaConstructorResolver constructorResolver) {
this.constructorResolver = constructorResolver;
}
@Nullable
public ClassDescriptor resolveClass(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule) {
return classResolver.resolveClass(qualifiedName, searchRule);
}
@Nullable
public NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule) {
return namespaceResolver.resolveNamespace(qualifiedName, searchRule);
}
@NotNull
public Set<FunctionDescriptor> resolveFunctionGroupForClass(@NotNull NamedMembers members, @NotNull ClassOrNamespaceDescriptor owner) {
return functionResolver.resolveFunctionGroupForClass(members, owner);
}
@NotNull
public Set<VariableDescriptor> resolveFieldGroup(@NotNull NamedMembers members, @NotNull ClassOrNamespaceDescriptor ownerDescriptor) {
return propertyResolver.resolveFieldGroup(members, ownerDescriptor);
}
@NotNull
public Collection<ConstructorDescriptor> resolveConstructors(@NotNull JavaClass javaClass, @NotNull ClassDescriptor classDescriptor) {
return constructorResolver.resolveConstructors(javaClass, classDescriptor);
}
}
@@ -1,261 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorParent;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.*;
import org.jetbrains.jet.lang.resolve.java.descriptor.JavaNamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap;
import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils;
import org.jetbrains.jet.lang.resolve.java.scope.JavaClassStaticMembersScope;
import org.jetbrains.jet.lang.resolve.java.scope.JavaPackageScope;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.java.structure.JavaField;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
import org.jetbrains.jet.lang.resolve.java.structure.JavaPackage;
import org.jetbrains.jet.lang.resolve.java.vfilefinder.VirtualFileFinder;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import javax.inject.Inject;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.INCLUDE_KOTLIN_SOURCES;
public final class JavaNamespaceResolver {
@NotNull
public static final ModuleDescriptor FAKE_ROOT_MODULE = new ModuleDescriptorImpl(JavaDescriptorResolver.JAVA_ROOT,
JavaBridgeConfiguration.ALL_JAVA_IMPORTS,
JavaToKotlinClassMap.getInstance());
@NotNull
private final Map<FqName, JetScope> resolvedNamespaceCache = new HashMap<FqName, JetScope>();
@NotNull
private final Set<FqName> unresolvedCache = new HashSet<FqName>();
private JavaClassFinder javaClassFinder;
private JavaResolverCache cache;
private JavaMemberResolver memberResolver;
private DeserializedDescriptorResolver deserializedDescriptorResolver;
private VirtualFileFinder virtualFileFinder;
@Inject
public void setVirtualFileFinder(VirtualFileFinder virtualFileFinder) {
this.virtualFileFinder = virtualFileFinder;
}
@Inject
public void setJavaClassFinder(JavaClassFinder javaClassFinder) {
this.javaClassFinder = javaClassFinder;
}
@Inject
public void setCache(JavaResolverCache cache) {
this.cache = cache;
}
@Inject
public void setMemberResolver(@NotNull JavaMemberResolver memberResolver) {
this.memberResolver = memberResolver;
}
@Inject
public void setDeserializedDescriptorResolver(DeserializedDescriptorResolver deserializedDescriptorResolver) {
this.deserializedDescriptorResolver = deserializedDescriptorResolver;
}
@Nullable
public NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule) {
// First, let's check that there is no Kotlin package:
NamespaceDescriptor kotlinNamespaceDescriptor = cache.getPackageResolvedFromSource(qualifiedName);
if (kotlinNamespaceDescriptor != null) {
return searchRule.processFoundInKotlin(kotlinNamespaceDescriptor);
}
if (unresolvedCache.contains(qualifiedName)) {
return null;
}
JetScope scope = resolvedNamespaceCache.get(qualifiedName);
if (scope != null) {
return (NamespaceDescriptor) scope.getContainingDeclaration();
}
NamespaceDescriptorParent parentNs = resolveParentNamespace(qualifiedName);
if (parentNs == null) {
return null;
}
JavaNamespaceDescriptor javaNamespaceDescriptor = new JavaNamespaceDescriptor(
parentNs,
Collections.<AnnotationDescriptor>emptyList(), // TODO
qualifiedName
);
JetScope newScope = createNamespaceScope(qualifiedName, javaNamespaceDescriptor, true);
if (newScope == null) {
return null;
}
javaNamespaceDescriptor.setMemberScope(newScope);
return javaNamespaceDescriptor;
}
@Nullable
private NamespaceDescriptorParent resolveParentNamespace(@NotNull FqName fqName) {
if (fqName.isRoot()) {
return FAKE_ROOT_MODULE;
}
else {
return resolveNamespace(fqName.parent(), INCLUDE_KOTLIN_SOURCES);
}
}
@Nullable
private JetScope createNamespaceScope(@NotNull FqName fqName, @NotNull NamespaceDescriptor namespaceDescriptor, boolean record) {
JetScope namespaceScope = doCreateNamespaceScope(fqName, namespaceDescriptor, record);
cache(fqName, namespaceScope);
return namespaceScope;
}
@Nullable
private JetScope doCreateNamespaceScope(
@NotNull FqName fqName,
@NotNull NamespaceDescriptor namespaceDescriptor,
boolean record
) {
JavaPackage javaPackage = javaClassFinder.findPackage(fqName);
if (javaPackage != null) {
FqName packageClassFqName = PackageClassUtils.getPackageClassFqName(fqName);
VirtualFile virtualFile = virtualFileFinder.find(packageClassFqName);
cache.recordProperNamespace(namespaceDescriptor);
if (virtualFile != null) {
JetScope kotlinPackageScope = deserializedDescriptorResolver.createKotlinPackageScope(namespaceDescriptor, virtualFile);
if (kotlinPackageScope != null) {
return kotlinPackageScope;
}
}
// Otherwise (if psiClass is null or doesn't have a supported Kotlin annotation), it's a Java class and the package is empty
if (record) {
cache.recordPackage(javaPackage, namespaceDescriptor);
}
return new JavaPackageScope(namespaceDescriptor, javaPackage, fqName, memberResolver);
}
JavaClass javaClass = javaClassFinder.findClass(fqName);
if (javaClass == null) {
return null;
}
if (DescriptorResolverUtils.isCompiledKotlinClassOrPackageClass(javaClass)) {
return null;
}
if (!hasStaticMembers(javaClass)) {
return null;
}
cache.recordClassStaticMembersNamespace(namespaceDescriptor);
if (record) {
cache.recordPackage(javaClass, namespaceDescriptor);
}
return new JavaClassStaticMembersScope(namespaceDescriptor, fqName, javaClass, memberResolver);
}
private void cache(@NotNull FqName fqName, @Nullable JetScope packageScope) {
if (packageScope == null) {
unresolvedCache.add(fqName);
return;
}
JetScope oldValue = resolvedNamespaceCache.put(fqName, packageScope);
if (oldValue != null) {
throw new IllegalStateException("rewrite at " + fqName);
}
}
@Nullable
public JetScope getJavaPackageScopeForExistingNamespaceDescriptor(@NotNull NamespaceDescriptor namespaceDescriptor) {
FqName fqName = DescriptorUtils.getFQName(namespaceDescriptor).toSafe();
if (unresolvedCache.contains(fqName)) {
throw new IllegalStateException(
"This means that we are trying to create a Java package, but have a package with the same FQN defined in Kotlin: " +
fqName);
}
JetScope alreadyResolvedScope = resolvedNamespaceCache.get(fqName);
if (alreadyResolvedScope != null) {
return alreadyResolvedScope;
}
return createNamespaceScope(fqName, namespaceDescriptor, false);
}
private static boolean hasStaticMembers(@NotNull JavaClass javaClass) {
for (JavaMethod method : javaClass.getMethods()) {
if (method.isStatic() && !DescriptorResolverUtils.shouldBeInEnumClassObject(method)) {
return true;
}
}
for (JavaField field : javaClass.getFields()) {
if (field.isStatic() && !DescriptorResolverUtils.shouldBeInEnumClassObject(field)) {
return true;
}
}
for (JavaClass nestedClass : javaClass.getInnerClasses()) {
if (SingleAbstractMethodUtils.isSamInterface(nestedClass)) {
return true;
}
if (nestedClass.isStatic() && hasStaticMembers(nestedClass)) {
return true;
}
}
return false;
}
@NotNull
public Collection<Name> getClassNamesInPackage(@NotNull FqName packageName) {
JavaPackage javaPackage = javaClassFinder.findPackage(packageName);
if (javaPackage == null) return Collections.emptyList();
Collection<JavaClass> classes = DescriptorResolverUtils.getClassesInPackage(javaPackage);
List<Name> result = new ArrayList<Name>(classes.size());
for (JavaClass javaClass : classes) {
if (DescriptorResolverUtils.isCompiledKotlinClass(javaClass)) {
result.add(javaClass.getName());
}
}
return result;
}
}
@@ -1,190 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.descriptor.JavaPropertyDescriptor;
import org.jetbrains.jet.lang.resolve.java.descriptor.JavaPropertyDescriptorForObject;
import org.jetbrains.jet.lang.resolve.java.scope.NamedMembers;
import org.jetbrains.jet.lang.resolve.java.structure.JavaField;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import javax.inject.Inject;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils.resolveOverrides;
public final class JavaPropertyResolver {
private JavaTypeTransformer typeTransformer;
private JavaResolverCache cache;
private JavaAnnotationResolver annotationResolver;
private ExternalSignatureResolver externalSignatureResolver;
private FakeOverrideVisibilityResolver fakeOverrideVisibilityResolver;
public JavaPropertyResolver() {
}
@Inject
public void setTypeTransformer(@NotNull JavaTypeTransformer javaTypeTransformer) {
this.typeTransformer = javaTypeTransformer;
}
@Inject
public void setCache(JavaResolverCache cache) {
this.cache = cache;
}
@Inject
public void setAnnotationResolver(JavaAnnotationResolver annotationResolver) {
this.annotationResolver = annotationResolver;
}
@Inject
public void setExternalSignatureResolver(ExternalSignatureResolver externalSignatureResolver) {
this.externalSignatureResolver = externalSignatureResolver;
}
@Inject
public void setFakeOverrideVisibilityResolver(FakeOverrideVisibilityResolver fakeOverrideVisibilityResolver) {
this.fakeOverrideVisibilityResolver = fakeOverrideVisibilityResolver;
}
@NotNull
public Set<VariableDescriptor> resolveFieldGroup(@NotNull NamedMembers members, @NotNull ClassOrNamespaceDescriptor owner) {
Name propertyName = members.getName();
List<JavaField> fields = members.getFields();
Set<PropertyDescriptor> propertiesFromCurrent = new HashSet<PropertyDescriptor>(1);
assert fields.size() <= 1;
if (fields.size() == 1) {
JavaField field = fields.iterator().next();
if (DescriptorResolverUtils.isCorrectOwnerForEnumMember(owner, field)) {
propertiesFromCurrent.add(resolveProperty(owner, propertyName, field));
}
}
Set<PropertyDescriptor> properties = new HashSet<PropertyDescriptor>();
if (owner instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) owner;
Collection<PropertyDescriptor> propertiesFromSupertypes = getPropertiesFromSupertypes(propertyName, classDescriptor);
properties.addAll(resolveOverrides(propertyName, propertiesFromSupertypes, propertiesFromCurrent, classDescriptor,
fakeOverrideVisibilityResolver));
}
properties.addAll(propertiesFromCurrent);
return new HashSet<VariableDescriptor>(properties);
}
@NotNull
private PropertyDescriptor resolveProperty(@NotNull ClassOrNamespaceDescriptor owner, @NotNull Name name, @NotNull JavaField field) {
boolean isVar = !field.isFinal();
PropertyDescriptorImpl propertyDescriptor = createPropertyDescriptor(owner, name, field, isVar);
propertyDescriptor.initialize(null, null);
TypeVariableResolver typeVariableResolver =
new TypeVariableResolver(Collections.<TypeParameterDescriptor>emptyList(), propertyDescriptor);
JetType propertyType = getPropertyType(field, typeVariableResolver);
ExternalSignatureResolver.AlternativeFieldSignature effectiveSignature =
externalSignatureResolver.resolveAlternativeFieldSignature(field, propertyType, isVar);
List<String> signatureErrors = effectiveSignature.getErrors();
if (!signatureErrors.isEmpty()) {
externalSignatureResolver.reportSignatureErrors(propertyDescriptor, signatureErrors);
}
propertyDescriptor.setType(
effectiveSignature.getReturnType(),
Collections.<TypeParameterDescriptor>emptyList(),
DescriptorUtils.getExpectedThisObjectIfNeeded(owner),
(JetType) null
);
cache.recordField(field, propertyDescriptor);
return propertyDescriptor;
}
@NotNull
private PropertyDescriptorImpl createPropertyDescriptor(
@NotNull ClassOrNamespaceDescriptor owner,
@NotNull Name propertyName,
@NotNull JavaField field,
boolean isVar
) {
List<AnnotationDescriptor> annotations = annotationResolver.resolveAnnotations(field);
Visibility visibility = field.getVisibility();
if (field.isEnumEntry()) {
assert !isVar : "Enum entries should be immutable.";
assert DescriptorUtils.isEnumClassObject(owner) : "Enum entries should be put into class object of enum only: " + owner;
//TODO: this is a hack to indicate that this enum entry is an object
// class descriptor for enum entries is not used by backends so for now this should be safe to use
ClassDescriptorImpl dummyClassDescriptorForEnumEntryObject =
new ClassDescriptorImpl(owner, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, propertyName);
dummyClassDescriptorForEnumEntryObject.initialize(
true,
Collections.<TypeParameterDescriptor>emptyList(),
Collections.<JetType>emptyList(), JetScope.EMPTY,
Collections.<ConstructorDescriptor>emptySet(), null,
false);
return new JavaPropertyDescriptorForObject(owner, annotations, visibility, propertyName, dummyClassDescriptorForEnumEntryObject);
}
return new JavaPropertyDescriptor(owner, annotations, visibility, isVar, propertyName);
}
@NotNull
private JetType getPropertyType(@NotNull JavaField field, @NotNull TypeVariableResolver typeVariableResolver) {
JetType propertyType = typeTransformer.transformToType(field.getType(), typeVariableResolver);
if (annotationResolver.hasNotNullAnnotation(field) || isStaticFinalField(field) /* TODO: WTF? */) {
return TypeUtils.makeNotNullable(propertyType);
}
return propertyType;
}
@NotNull
private static Set<PropertyDescriptor> getPropertiesFromSupertypes(@NotNull Name name, @NotNull ClassDescriptor descriptor) {
Set<PropertyDescriptor> result = new HashSet<PropertyDescriptor>();
for (JetType supertype : descriptor.getTypeConstructor().getSupertypes()) {
for (VariableDescriptor property : supertype.getMemberScope().getProperties(name)) {
result.add((PropertyDescriptor) property);
}
}
return result;
}
private static boolean isStaticFinalField(@NotNull JavaField field) {
return field.isFinal() && field.isStatic();
}
}
@@ -1,57 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.java.structure.JavaElement;
import org.jetbrains.jet.lang.resolve.java.structure.JavaField;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
import org.jetbrains.jet.lang.resolve.name.FqName;
public interface JavaResolverCache {
@Nullable
ClassDescriptor getClassResolvedFromSource(@NotNull FqName fqName);
@Nullable
NamespaceDescriptor getPackageResolvedFromSource(@NotNull FqName fqName);
@Nullable
SimpleFunctionDescriptor getMethod(@NotNull JavaMethod method);
@Nullable
ConstructorDescriptor getConstructor(@NotNull JavaElement constructor);
@Nullable
ClassDescriptor getClass(@NotNull JavaClass javaClass);
void recordMethod(@NotNull JavaMethod method, @NotNull SimpleFunctionDescriptor descriptor);
void recordConstructor(@NotNull JavaElement element, @NotNull ConstructorDescriptor descriptor);
void recordField(@NotNull JavaField field, @NotNull PropertyDescriptor descriptor);
void recordClass(@NotNull JavaClass javaClass, @NotNull ClassDescriptor descriptor);
void recordProperNamespace(@NotNull NamespaceDescriptor descriptor);
void recordClassStaticMembersNamespace(@NotNull NamespaceDescriptor descriptor);
void recordPackage(@NotNull JavaElement element, @NotNull NamespaceDescriptor descriptor);
}
@@ -1,114 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClassifier;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClassifierType;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.IGNORE_KOTLIN_SOURCES;
public final class JavaSupertypeResolver {
public static final FqName OBJECT_FQ_NAME = new FqName("java.lang.Object");
private JavaTypeTransformer typeTransformer;
private JavaClassResolver classResolver;
@Inject
public void setTypeTransformer(JavaTypeTransformer typeTransformer) {
this.typeTransformer = typeTransformer;
}
@Inject
public void setClassResolver(JavaClassResolver classResolver) {
this.classResolver = classResolver;
}
@NotNull
public Collection<JetType> getSupertypes(
@NotNull ClassDescriptor classDescriptor,
@NotNull JavaClass javaClass,
@NotNull List<TypeParameterDescriptor> typeParameters
) {
TypeVariableResolver typeVariableResolver = new TypeVariableResolver(typeParameters, classDescriptor);
List<JetType> result = transformSupertypeList(javaClass.getSupertypes(), typeVariableResolver);
return result.isEmpty() ? Collections.singletonList(getDefaultSupertype(javaClass)) : result;
}
@NotNull
private JetType getDefaultSupertype(@NotNull JavaClass javaClass) {
if (OBJECT_FQ_NAME.equals(javaClass.getFqName()) || javaClass.isAnnotationType()) {
return KotlinBuiltIns.getInstance().getAnyType();
}
else {
ClassDescriptor object = classResolver.resolveClass(OBJECT_FQ_NAME, IGNORE_KOTLIN_SOURCES);
if (object != null) {
return object.getDefaultType();
}
else {
//TODO: hack here
return KotlinBuiltIns.getInstance().getAnyType();
// throw new IllegalStateException("Could not resolve java.lang.Object");
}
}
}
@NotNull
private List<JetType> transformSupertypeList(
@NotNull Collection<JavaClassifierType> supertypes,
@NotNull TypeVariableResolver typeVariableResolver
) {
List<JetType> result = new ArrayList<JetType>(supertypes.size());
for (JavaClassifierType type : supertypes) {
JavaClassifier resolved = type.getClassifier();
if (resolved != null) {
assert resolved instanceof JavaClass : "Supertype should be a class: " + resolved;
FqName fqName = ((JavaClass) resolved).getFqName();
assert fqName != null : "Unresolved supertype: " + resolved;
if (JvmAbi.JET_OBJECT.getFqName().equals(fqName)) {
continue;
}
}
JetType transformed = typeTransformer.transformToType(type, TypeUsage.SUPERTYPE, typeVariableResolver);
if (ErrorUtils.isErrorType(transformed)) {
// TODO: report INCOMPLETE_HIERARCHY
}
else {
result.add(TypeUtils.makeNotNullable(transformed));
}
}
return result;
}
}
@@ -1,104 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClassifierType;
import org.jetbrains.jet.lang.resolve.java.structure.JavaTypeParameter;
import org.jetbrains.jet.lang.resolve.java.structure.JavaTypeParameterListOwner;
import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import javax.inject.Inject;
import java.util.*;
public final class JavaTypeParameterResolver {
@NotNull
private JavaTypeTransformer typeTransformer;
@Inject
public void setTypeTransformer(@NotNull JavaTypeTransformer javaTypeTransformer) {
this.typeTransformer = javaTypeTransformer;
}
@NotNull
public Initializer resolveTypeParameters(
@NotNull DeclarationDescriptor ownerDescriptor,
@NotNull JavaTypeParameterListOwner typeParameterListOwner
) {
Initializer result = new Initializer(ownerDescriptor);
for (JavaTypeParameter typeParameter : typeParameterListOwner.getTypeParameters()) {
result.addTypeParameter(typeParameter);
}
return result;
}
public class Initializer {
private final DeclarationDescriptor owner;
private final List<TypeParameterDescriptor> descriptors = new ArrayList<TypeParameterDescriptor>();
private final List<JavaTypeParameter> javaTypeParameters = new ArrayList<JavaTypeParameter>();
private Initializer(@NotNull DeclarationDescriptor owner) {
this.owner = owner;
}
private void addTypeParameter(@NotNull JavaTypeParameter typeParameter) {
TypeParameterDescriptorImpl descriptor = TypeParameterDescriptorImpl.createForFurtherModification(
owner,
Collections.<AnnotationDescriptor>emptyList(), // TODO
false,
Variance.INVARIANT,
typeParameter.getName(),
typeParameter.getIndex()
);
descriptors.add(descriptor);
javaTypeParameters.add(typeParameter);
}
@NotNull
public List<TypeParameterDescriptor> getDescriptors() {
return descriptors;
}
public void initialize() {
TypeVariableResolver typeVariableResolver = new TypeVariableResolver(getDescriptors(), owner);
Iterator<TypeParameterDescriptor> descriptorIterator = descriptors.iterator();
Iterator<JavaTypeParameter> typeParameterIterator = javaTypeParameters.iterator();
while (descriptorIterator.hasNext()) {
TypeParameterDescriptorImpl descriptor = (TypeParameterDescriptorImpl) descriptorIterator.next();
Collection<JavaClassifierType> upperBounds = typeParameterIterator.next().getUpperBounds();
if (upperBounds.isEmpty()) {
descriptor.addUpperBound(KotlinBuiltIns.getInstance().getDefaultBound());
}
else {
for (JavaClassifierType upperBound : upperBounds) {
descriptor.addUpperBound(typeTransformer.transformToType(upperBound, TypeUsage.UPPER_BOUND, typeVariableResolver));
}
}
descriptor.setInitialized();
}
}
}
}
@@ -1,279 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap;
import org.jetbrains.jet.lang.resolve.java.structure.*;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import javax.inject.Inject;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.INCLUDE_KOTLIN_SOURCES;
import static org.jetbrains.jet.lang.resolve.java.resolver.TypeUsage.*;
import static org.jetbrains.jet.lang.types.Variance.*;
public class JavaTypeTransformer {
private static final Logger LOG = Logger.getInstance(JavaTypeTransformer.class);
private JavaClassResolver classResolver;
@Inject
public void setClassResolver(JavaClassResolver classResolver) {
this.classResolver = classResolver;
}
@NotNull
private TypeProjection transformToTypeProjection(
@NotNull JavaType type,
@NotNull TypeParameterDescriptor typeParameterDescriptor,
@NotNull TypeVariableResolver typeVariableResolver,
@NotNull TypeUsage howThisTypeIsUsed
) {
if (!(type instanceof JavaWildcardType)) {
return new TypeProjection(transformToType(type, howThisTypeIsUsed, typeVariableResolver));
}
JavaWildcardType wildcardType = (JavaWildcardType) type;
JavaType bound = wildcardType.getBound();
if (bound == null) {
return SubstitutionUtils.makeStarProjection(typeParameterDescriptor);
}
Variance variance = wildcardType.isExtends() ? OUT_VARIANCE : IN_VARIANCE;
return new TypeProjection(variance, transformToType(bound, UPPER_BOUND, typeVariableResolver));
}
@NotNull
public JetType transformToType(@NotNull JavaType type, @NotNull TypeVariableResolver typeVariableResolver) {
return transformToType(type, TypeUsage.MEMBER_SIGNATURE_INVARIANT, typeVariableResolver);
}
@NotNull
public JetType transformToType(
@NotNull JavaType type,
@NotNull TypeUsage howThisTypeIsUsed,
@NotNull TypeVariableResolver typeVariableResolver
) {
if (type instanceof JavaClassifierType) {
JavaClassifierType classifierType = (JavaClassifierType) type;
JetType jetType = transformClassifierType(classifierType, howThisTypeIsUsed, typeVariableResolver);
if (jetType == null) {
return ErrorUtils.createErrorType("Unresolved java class: " + classifierType.getPresentableText());
}
return jetType;
}
else if (type instanceof JavaPrimitiveType) {
String canonicalText = ((JavaPrimitiveType) type).getCanonicalText();
JetType jetType = JavaToKotlinClassMap.getInstance().mapPrimitiveKotlinClass(canonicalText);
assert jetType != null : "Primitive type is not found: " + canonicalText;
return jetType;
}
else if (type instanceof JavaArrayType) {
return transformArrayType((JavaArrayType) type, howThisTypeIsUsed, typeVariableResolver, false);
}
else {
throw new UnsupportedOperationException("Unsupported type: " + type); // TODO
}
}
@Nullable
private JetType transformClassifierType(
@NotNull JavaClassifierType classifierType,
@NotNull TypeUsage howThisTypeIsUsed,
@NotNull TypeVariableResolver typeVariableResolver
) {
JavaClassifier javaClassifier = classifierType.getClassifier();
if (javaClassifier == null) {
return null;
}
if (javaClassifier instanceof JavaTypeParameter) {
return transformTypeParameter((JavaTypeParameter) javaClassifier, howThisTypeIsUsed, typeVariableResolver);
}
else if (javaClassifier instanceof JavaClass) {
FqName fqName = ((JavaClass) javaClassifier).getFqName();
assert fqName != null : "Class type should have a FQ name: " + javaClassifier;
return transformClassType(fqName, classifierType, howThisTypeIsUsed, typeVariableResolver);
}
else {
throw new UnsupportedOperationException("Unsupported classifier: " + javaClassifier);
}
}
@Nullable
private JetType transformTypeParameter(
@NotNull JavaTypeParameter typeParameter,
@NotNull TypeUsage howThisTypeIsUsed,
@NotNull TypeVariableResolver typeVariableResolver
) {
JavaTypeParameterListOwner owner = typeParameter.getOwner();
if (owner instanceof JavaMethod && ((JavaMethod) owner).isConstructor()) {
Set<JetType> supertypesJet = new HashSet<JetType>();
for (JavaClassifierType supertype : typeParameter.getUpperBounds()) {
supertypesJet.add(transformToType(supertype, UPPER_BOUND, typeVariableResolver));
}
return TypeUtils.intersect(JetTypeChecker.INSTANCE, supertypesJet);
}
TypeParameterDescriptor typeParameterDescriptor = typeVariableResolver.getTypeVariable(typeParameter.getName());
// In Java: ArrayList<T>
// In Kotlin: ArrayList<T>, not ArrayList<T?>
// nullability will be taken care of in individual member signatures
boolean nullable = !EnumSet.of(TYPE_ARGUMENT, UPPER_BOUND, SUPERTYPE_ARGUMENT).contains(howThisTypeIsUsed);
return TypeUtils.makeNullableIfNeeded(typeParameterDescriptor.getDefaultType(), nullable);
}
@Nullable
private JetType transformClassType(
@NotNull FqName fqName,
@NotNull JavaClassifierType classifierType,
@NotNull TypeUsage howThisTypeIsUsed,
@NotNull TypeVariableResolver typeVariableResolver
) {
// 'L extends List<T>' in Java is a List<T> in Kotlin, not a List<T?>
boolean nullable = !EnumSet.of(TYPE_ARGUMENT, SUPERTYPE_ARGUMENT, SUPERTYPE).contains(howThisTypeIsUsed);
ClassDescriptor classData = JavaToKotlinClassMap.getInstance().mapKotlinClass(fqName, howThisTypeIsUsed);
if (classData == null) {
classData = classResolver.resolveClass(fqName, INCLUDE_KOTLIN_SOURCES);
}
if (classData == null) {
return null;
}
List<TypeProjection> arguments = new ArrayList<TypeProjection>();
List<TypeParameterDescriptor> parameters = classData.getTypeConstructor().getParameters();
if (isRaw(classifierType, !parameters.isEmpty())) {
for (TypeParameterDescriptor parameter : parameters) {
// not making a star projection because of this case:
// Java:
// class C<T extends C> {}
// The upper bound is raw here, and we can't compute the projection: it would be infinite:
// C<*> = C<out C<out C<...>>>
// this way we loose some type information, even when the case is not so bad, but it doesn't seem to matter
// projections are not allowed in immediate arguments of supertypes
Variance projectionKind = parameter.getVariance() == OUT_VARIANCE || howThisTypeIsUsed == SUPERTYPE
? INVARIANT
: OUT_VARIANCE;
arguments.add(new TypeProjection(projectionKind, KotlinBuiltIns.getInstance().getNullableAnyType()));
}
}
else {
Collection<JavaType> javaTypeArguments = classifierType.getTypeArguments();
if (parameters.size() != javaTypeArguments.size()) {
// Most of the time this means there is an error in the Java code
LOG.warn("parameters = " + parameters.size() + ", actual arguments = " + javaTypeArguments.size() +
" in " + classifierType.getPresentableText() + "\n fqName: \n" + fqName);
for (TypeParameterDescriptor parameter : parameters) {
arguments.add(new TypeProjection(ErrorUtils.createErrorType(parameter.getName().asString())));
}
}
else {
int index = 0;
for (JavaType typeArgument : javaTypeArguments) {
TypeParameterDescriptor typeParameterDescriptor = parameters.get(index);
index++;
TypeUsage howTheProjectionIsUsed = howThisTypeIsUsed == SUPERTYPE ? SUPERTYPE_ARGUMENT : TYPE_ARGUMENT;
TypeProjection typeProjection = transformToTypeProjection(typeArgument, typeParameterDescriptor, typeVariableResolver,
howTheProjectionIsUsed);
if (typeProjection.getProjectionKind() == typeParameterDescriptor.getVariance()) {
// remove redundant 'out' and 'in'
arguments.add(new TypeProjection(INVARIANT, typeProjection.getType()));
}
else {
arguments.add(typeProjection);
}
}
}
}
return new JetTypeImpl(
Collections.<AnnotationDescriptor>emptyList(),
classData.getTypeConstructor(),
nullable,
arguments,
classData.getMemberScope(arguments));
}
@NotNull
private JetType transformArrayType(
@NotNull JavaArrayType arrayType,
@NotNull TypeUsage howThisTypeIsUsed,
@NotNull TypeVariableResolver typeVariableResolver,
boolean vararg
) {
JavaType componentType = arrayType.getComponentType();
if (componentType instanceof JavaPrimitiveType) {
JetType jetType = JavaToKotlinClassMap.getInstance().mapPrimitiveKotlinClass(
"[" + ((JavaPrimitiveType) componentType).getCanonicalText());
if (jetType != null) {
return TypeUtils.makeNullable(jetType);
}
}
Variance projectionKind = arrayElementTypeProjectionKind(howThisTypeIsUsed, vararg);
TypeUsage howArgumentTypeIsUsed = vararg ? MEMBER_SIGNATURE_CONTRAVARIANT : TYPE_ARGUMENT;
JetType type = transformToType(componentType, howArgumentTypeIsUsed, typeVariableResolver);
return TypeUtils.makeNullable(KotlinBuiltIns.getInstance().getArrayType(projectionKind, type));
}
@NotNull
private static Variance arrayElementTypeProjectionKind(@NotNull TypeUsage howThisTypeIsUsed, boolean vararg) {
if (howThisTypeIsUsed == MEMBER_SIGNATURE_CONTRAVARIANT && !vararg) {
return OUT_VARIANCE;
}
else {
return INVARIANT;
}
}
@NotNull
public JetType transformVarargType(
@NotNull JavaArrayType type,
@NotNull TypeUsage howThisTypeIsUsed,
@NotNull TypeVariableResolver typeVariableResolver
) {
return transformArrayType(type, howThisTypeIsUsed, typeVariableResolver, true);
}
private static boolean isRaw(@NotNull JavaClassifierType classifierType, boolean argumentsExpected) {
// The second option is needed because sometimes we get weird versions of JDK classes in the class path,
// such as collections with no generics, so the Java types are not raw, formally, but they don't match with
// their Kotlin analogs, so we treat them as raw to avoid exceptions
return classifierType.isRaw() || argumentsExpected && classifierType.getTypeArguments().isEmpty();
}
}
@@ -1,118 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
import org.jetbrains.jet.lang.resolve.java.structure.JavaArrayType;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
import org.jetbrains.jet.lang.resolve.java.structure.JavaType;
import org.jetbrains.jet.lang.resolve.java.structure.JavaValueParameter;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public final class JavaValueParameterResolver {
private JavaAnnotationResolver annotationResolver;
private JavaTypeTransformer typeTransformer;
@Inject
public void setAnnotationResolver(JavaAnnotationResolver annotationResolver) {
this.annotationResolver = annotationResolver;
}
@Inject
public void setTypeTransformer(JavaTypeTransformer typeTransformer) {
this.typeTransformer = typeTransformer;
}
@NotNull
private ValueParameterDescriptor resolveValueParameter(
@NotNull DeclarationDescriptor containingDeclaration,
int i,
@NotNull JavaValueParameter parameter,
@NotNull TypeVariableResolver typeVariableResolver
) {
TypeUsage typeUsage = annotationResolver.hasMutableAnnotation(parameter)
? TypeUsage.MEMBER_SIGNATURE_COVARIANT
: TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT;
JavaType parameterType = parameter.getType();
JetType varargElementType;
JetType outType;
if (parameter.isVararg()) {
// TODO: test this code
assert parameterType instanceof JavaArrayType : "Vararg parameter should be an array: " + parameterType;
JetType arrayType = typeTransformer.transformVarargType(((JavaArrayType) parameterType), typeUsage, typeVariableResolver);
outType = TypeUtils.makeNotNullable(arrayType);
varargElementType = KotlinBuiltIns.getInstance().getArrayElementType(outType);
}
else {
JetType transformedType = typeTransformer.transformToType(parameterType, typeUsage, typeVariableResolver);
if (transformedType.isNullable() && annotationResolver.hasNotNullAnnotation(parameter)) {
transformedType = TypeUtils.makeNotNullable(transformedType);
}
outType = transformedType;
varargElementType = null;
}
return new ValueParameterDescriptorImpl(
containingDeclaration,
i,
Collections.<AnnotationDescriptor>emptyList(), // TODO
getParameterName(i, parameter), // TODO: must be very slow, make it lazy?
outType,
false,
varargElementType
);
}
@NotNull
private static Name getParameterName(int number, @NotNull JavaValueParameter parameter) {
Name psiParameterName = parameter.getName();
return psiParameterName != null ? psiParameterName : Name.identifier("p" + number);
}
@NotNull
public List<ValueParameterDescriptor> resolveValueParameters(
@NotNull DeclarationDescriptor container,
@NotNull JavaMethod method,
@NotNull TypeVariableResolver typeVariableResolver
) {
Collection<JavaValueParameter> parameters = method.getValueParameters();
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(parameters.size());
int index = 0;
for (JavaValueParameter parameter : parameters) {
result.add(resolveValueParameter(container, index, parameter, typeVariableResolver));
index++;
}
return result;
}
}
@@ -1,213 +0,0 @@
package org.jetbrains.jet.lang.resolve.java.resolver;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.AnnotationVisitor;
import org.jetbrains.asm4.ClassReader;
import org.jetbrains.asm4.ClassVisitor;
import org.jetbrains.asm4.Opcodes;
import org.jetbrains.jet.descriptors.serialization.ClassData;
import org.jetbrains.jet.descriptors.serialization.JavaProtoBufUtil;
import org.jetbrains.jet.descriptors.serialization.PackageData;
import org.jetbrains.jet.lang.resolve.java.AbiVersionUtil;
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.utils.ExceptionUtils;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.asm4.ClassReader.*;
import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCompatible;
public final class KotlinClassFileHeader {
@NotNull
public static KotlinClassFileHeader readKotlinHeaderFromClassFile(@NotNull VirtualFile virtualFile) {
try {
InputStream inputStream = virtualFile.getInputStream();
try {
ClassReader reader = new ClassReader(inputStream);
KotlinClassFileHeader classFileData = new KotlinClassFileHeader();
reader.accept(classFileData.new ReadDataFromAnnotationVisitor(), SKIP_CODE | SKIP_FRAMES | SKIP_DEBUG);
return classFileData;
}
finally {
inputStream.close();
}
}
catch (IOException e) {
throw ExceptionUtils.rethrow(e);
}
}
@SuppressWarnings("deprecation")
public enum HeaderType {
CLASS(JvmAnnotationNames.KOTLIN_CLASS),
PACKAGE(JvmAnnotationNames.KOTLIN_PACKAGE),
OLD_CLASS(JvmAnnotationNames.OLD_JET_CLASS_ANNOTATION),
OLD_PACKAGE(JvmAnnotationNames.OLD_JET_PACKAGE_CLASS_ANNOTATION),
NONE(null);
@Nullable
private final JvmClassName correspondingAnnotation;
HeaderType(@Nullable JvmClassName annotation) {
correspondingAnnotation = annotation;
}
boolean isValidAnnotation() {
return this == CLASS || this == PACKAGE;
}
@NotNull
public static HeaderType byDescriptor(@NotNull String desc) {
for (HeaderType headerType : HeaderType.values()) {
JvmClassName annotation = headerType.correspondingAnnotation;
if (annotation == null) {
continue;
}
if (desc.equals(annotation.getDescriptor())) {
return headerType;
}
}
return NONE;
}
}
private int version = AbiVersionUtil.INVALID_VERSION;
@Nullable
private String[] annotationData = null;
@NotNull
HeaderType type = HeaderType.NONE;
@Nullable
JvmClassName jvmClassName = null;
public int getVersion() {
return version;
}
@NotNull
public HeaderType getType() {
return type;
}
/*
Checks that this is a header for compiled Kotlin file with correct abi version which can be processed by compiler or the IDE.
*/
public boolean isKotlinCompiledFile() {
return type.isValidAnnotation() && isAbiVersionCompatible(version);
}
/**
* @return FQ name for class header or package class FQ name for package header (e.g. <code>test.TestPackage</code>)
*/
@NotNull
public FqName getFqName() {
assert jvmClassName != null;
return jvmClassName.getFqName();
}
public String[] getAnnotationData() {
assertDataRead();
return annotationData;
}
private void assertDataRead() {
if (annotationData == null && type != HeaderType.NONE) {
throw new IllegalStateException("Data for annotations " + type.correspondingAnnotation + " was not read.");
}
}
@NotNull
public ClassData readClassData() {
assert type == HeaderType.CLASS;
return JavaProtoBufUtil.readClassDataFrom(getAnnotationData());
}
@NotNull
public PackageData readPackageData() {
assert type == HeaderType.PACKAGE;
return JavaProtoBufUtil.readPackageDataFrom(getAnnotationData());
}
private class ReadDataFromAnnotationVisitor extends ClassVisitor {
public ReadDataFromAnnotationVisitor() {
super(Opcodes.ASM4);
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
jvmClassName = JvmClassName.byInternalName(name);
}
@Override
public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
HeaderType headerTypeByAnnotation = HeaderType.byDescriptor(desc);
if (headerTypeByAnnotation == HeaderType.NONE) {
return null;
}
if (headerTypeByAnnotation.isValidAnnotation() && type.isValidAnnotation()) {
throw new IllegalStateException("Both " + type.correspondingAnnotation + " and "
+ headerTypeByAnnotation.correspondingAnnotation + " present!");
}
if (!type.isValidAnnotation()) {
type = headerTypeByAnnotation;
}
if (!headerTypeByAnnotation.isValidAnnotation()) {
return null;
}
return new AnnotationVisitor(Opcodes.ASM4) {
@Override
public void visit(String name, Object value) {
if (name.equals(JvmAnnotationNames.ABI_VERSION_FIELD_NAME)) {
version = (Integer) value;
}
else if (isAbiVersionCompatible(version)) {
throw new IllegalStateException("Unexpected argument " + name + " for annotation " + desc);
}
}
@Override
public AnnotationVisitor visitArray(String name) {
if (name.equals(JvmAnnotationNames.DATA_FIELD_NAME)) {
return stringArrayVisitor();
}
else if (isAbiVersionCompatible(version)) {
throw new IllegalStateException("Unexpected array argument " + name + " for annotation " + desc);
}
return super.visitArray(name);
}
@NotNull
private AnnotationVisitor stringArrayVisitor() {
final List<String> strings = new ArrayList<String>(1);
return new AnnotationVisitor(Opcodes.ASM4) {
@Override
public void visit(String name, Object value) {
if (!(value instanceof String)) {
throw new IllegalStateException("Unexpected argument value: " + value);
}
strings.add((String) value);
}
@Override
public void visitEnd() {
annotationData = strings.toArray(new String[strings.size()]);
}
};
}
};
}
}
private KotlinClassFileHeader() {
}
}
@@ -1,34 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
import java.util.List;
public interface MethodSignatureChecker {
void checkSignature(
@NotNull JavaMethod method,
boolean reportSignatureErrors,
@NotNull SimpleFunctionDescriptor descriptor,
@NotNull List<String> signatureErrors,
@NotNull List<FunctionDescriptor> superFunctions
);
}
@@ -1,38 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public final class PostponedTasks {
@NotNull
private final List<Runnable> tasks = new ArrayList<Runnable>();
public void addTask(@NotNull Runnable runnable) {
tasks.add(runnable);
}
public void performTasks() {
for (Runnable task : tasks) {
task.run();
}
}
}
@@ -1,39 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
import java.util.ServiceLoader;
public abstract class ProgressChecker {
private static ProgressChecker instance;
@NotNull
public static ProgressChecker getInstance() {
if (instance == null) {
Iterator<ProgressChecker> iterator =
ServiceLoader.load(ProgressChecker.class, ProgressChecker.class.getClassLoader()).iterator();
assert iterator.hasNext() : "No service found: " + ProgressChecker.class.getName();
instance = iterator.next();
}
return instance;
}
public abstract void checkCanceled();
}
@@ -1,32 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
/**
* We convert Java types differently, depending on where they occur in the Java code
* This enum encodes the kinds of occurrences
*/
public enum TypeUsage {
// Type T occurs somewhere as a generic argument, e.g.: List<T> or List<? extends T>
TYPE_ARGUMENT,
UPPER_BOUND,
MEMBER_SIGNATURE_COVARIANT,
MEMBER_SIGNATURE_CONTRAVARIANT,
MEMBER_SIGNATURE_INVARIANT,
SUPERTYPE,
SUPERTYPE_ARGUMENT
}
@@ -1,73 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.resolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.List;
/* package */ class TypeVariableResolver {
@NotNull
private final List<TypeParameterDescriptor> typeParameters;
@NotNull
private final DeclarationDescriptor owner;
public TypeVariableResolver(@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull DeclarationDescriptor owner) {
this.typeParameters = typeParameters;
this.owner = owner;
assert parametersBelongToOwner() : "Type parameters should belong to owner: " + owner + "; " + typeParameters;
}
private boolean parametersBelongToOwner() {
for (TypeParameterDescriptor typeParameter : typeParameters) {
if (typeParameter.getContainingDeclaration() != owner) {
return false;
}
}
return true;
}
@NotNull
public TypeParameterDescriptor getTypeVariable(@NotNull Name name) {
return getTypeVariable(name, typeParameters, owner);
}
@NotNull
private static TypeParameterDescriptor getTypeVariable(
@NotNull Name name,
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull DeclarationDescriptor owner
) {
for (TypeParameterDescriptor typeParameter : typeParameters) {
if (typeParameter.getName().equals(name)) {
return typeParameter;
}
}
DeclarationDescriptor container = owner.getContainingDeclaration();
if (container instanceof ClassDescriptor) {
return getTypeVariable(name, ((ClassDescriptor) container).getTypeConstructor().getParameters(), container);
}
throw new IllegalStateException("Type parameter not found by name: " + name);
}
}
@@ -1,38 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.sam;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl;
import org.jetbrains.jet.lang.resolve.java.descriptor.SamAdapterDescriptor;
/* package */ class SamAdapterConstructorDescriptor extends ConstructorDescriptorImpl
implements SamAdapterDescriptor<ConstructorDescriptor> {
private final ConstructorDescriptor declaration;
public SamAdapterConstructorDescriptor(@NotNull ConstructorDescriptor declaration) {
super(declaration.getContainingDeclaration(), declaration.getAnnotations(), declaration.isPrimary(), Kind.SYNTHESIZED);
this.declaration = declaration;
}
@NotNull
@Override
public ConstructorDescriptor getBaseForSynthesized() {
return declaration;
}
}
@@ -1,38 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.sam;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.resolve.java.descriptor.SamAdapterDescriptor;
/* package */ class SamAdapterFunctionDescriptor extends SimpleFunctionDescriptorImpl
implements SamAdapterDescriptor<SimpleFunctionDescriptor> {
private final SimpleFunctionDescriptor declaration;
public SamAdapterFunctionDescriptor(@NotNull SimpleFunctionDescriptor declaration) {
super(declaration.getContainingDeclaration(), declaration.getAnnotations(), declaration.getName(), Kind.SYNTHESIZED);
this.declaration = declaration;
}
@NotNull
@Override
public SimpleFunctionDescriptor getBaseForSynthesized() {
return declaration;
}
}
@@ -1,104 +0,0 @@
package org.jetbrains.jet.lang.resolve.java.sam;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.resolve.ExternalOverridabilityCondition;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import org.jetbrains.jet.lang.types.TypeUtils;
import java.util.List;
public class SamAdapterOverridabilityCondition implements ExternalOverridabilityCondition {
@Override
public boolean isOverridable(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
if (subDescriptor instanceof PropertyDescriptor) {
return true;
}
SimpleFunctionDescriptor superOriginal = getOriginalOfSamAdapterFunction((SimpleFunctionDescriptor) superDescriptor);
SimpleFunctionDescriptor subOriginal = getOriginalOfSamAdapterFunction((SimpleFunctionDescriptor) subDescriptor);
if (superOriginal == null || subOriginal == null) { // super or sub is/overrides DECLARATION
return subOriginal == null; // DECLARATION can override anything
}
// inheritor if SYNTHESIZED can override inheritor of SYNTHESIZED if their originals have same erasure
return equalErasure(superOriginal, subOriginal);
}
private static boolean equalErasure(@NotNull FunctionDescriptor fun1, @NotNull FunctionDescriptor fun2) {
List<ValueParameterDescriptor> parameters1 = fun1.getValueParameters();
List<ValueParameterDescriptor> parameters2 = fun2.getValueParameters();
for (ValueParameterDescriptor param1 : parameters1) {
ValueParameterDescriptor param2 = parameters2.get(param1.getIndex());
if (!TypeUtils.equalClasses(param2.getType(), param1.getType())) {
return false;
}
}
return true;
}
// if function is or overrides declaration, returns null; otherwise, return original of sam adapter with substituted type parameters
@Nullable
private static SimpleFunctionDescriptor getOriginalOfSamAdapterFunction(@NotNull SimpleFunctionDescriptor callable) {
DeclarationDescriptor containingDeclaration = callable.getContainingDeclaration();
if (!(containingDeclaration instanceof ClassDescriptor)) {
return null;
}
SamAdapterInfo declarationOrSynthesized =
getNearestDeclarationOrSynthesized(callable, ((ClassDescriptor) containingDeclaration).getDefaultType());
if (declarationOrSynthesized == null) {
return null;
}
SimpleFunctionDescriptorImpl fun = (SimpleFunctionDescriptorImpl) declarationOrSynthesized.samAdapter.getOriginal();
if (!(fun instanceof SamAdapterFunctionDescriptor)) {
return null;
}
SimpleFunctionDescriptor originalDeclarationOfSam = ((SamAdapterFunctionDescriptor) fun).getBaseForSynthesized();
return ((SimpleFunctionDescriptor) originalDeclarationOfSam.substitute(TypeSubstitutor.create(declarationOrSynthesized.ownerType)));
}
@Nullable
private static SamAdapterInfo getNearestDeclarationOrSynthesized(
@NotNull SimpleFunctionDescriptor samAdapter,
@NotNull JetType ownerType
) {
if (samAdapter.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
return new SamAdapterInfo(samAdapter, ownerType);
}
for (CallableMemberDescriptor overridden : samAdapter.getOverriddenDescriptors()) {
ClassDescriptor containingClass = (ClassDescriptor) overridden.getContainingDeclaration();
for (JetType immediateSupertype : TypeUtils.getImmediateSupertypes(ownerType)) {
if (containingClass != immediateSupertype.getConstructor().getDeclarationDescriptor()) {
continue;
}
SamAdapterInfo found = getNearestDeclarationOrSynthesized((SimpleFunctionDescriptor) overridden, immediateSupertype);
if (found != null) {
return found;
}
}
}
return null;
}
private static class SamAdapterInfo {
private final SimpleFunctionDescriptor samAdapter;
private final JetType ownerType;
private SamAdapterInfo(@NotNull SimpleFunctionDescriptor samAdapter, @NotNull JetType ownerType) {
this.samAdapter = samAdapter;
this.ownerType = ownerType;
}
}
}
@@ -1,422 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.sam;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
import org.jetbrains.jet.lang.resolve.java.descriptor.SamAdapterDescriptor;
import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptor;
import org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils;
import org.jetbrains.jet.lang.resolve.java.resolver.JavaSupertypeResolver;
import org.jetbrains.jet.lang.resolve.java.structure.*;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils.erasure;
import static org.jetbrains.jet.lang.types.Variance.INVARIANT;
public class SingleAbstractMethodUtils {
private SingleAbstractMethodUtils() {
}
@NotNull
public static List<CallableMemberDescriptor> getAbstractMembers(@NotNull JetType type) {
List<CallableMemberDescriptor> abstractMembers = new ArrayList<CallableMemberDescriptor>();
for (DeclarationDescriptor member : type.getMemberScope().getAllDescriptors()) {
if (member instanceof CallableMemberDescriptor && ((CallableMemberDescriptor) member).getModality() == Modality.ABSTRACT) {
abstractMembers.add((CallableMemberDescriptor) member);
}
}
return abstractMembers;
}
private static JetType fixProjections(@NotNull JetType functionType) {
//removes redundant projection kinds and detects conflicts
List<TypeParameterDescriptor> typeParameters = functionType.getConstructor().getParameters();
List<TypeProjection> arguments = new ArrayList<TypeProjection>(typeParameters.size());
for (TypeParameterDescriptor typeParameter : typeParameters) {
Variance variance = typeParameter.getVariance();
TypeProjection argument = functionType.getArguments().get(typeParameter.getIndex());
Variance kind = argument.getProjectionKind();
if (kind != INVARIANT && variance != INVARIANT) {
if (kind == variance) {
arguments.add(new TypeProjection(argument.getType()));
}
else {
return null;
}
}
else {
arguments.add(argument);
}
}
ClassifierDescriptor classifier = functionType.getConstructor().getDeclarationDescriptor();
assert classifier instanceof ClassDescriptor : "Not class: " + classifier;
return new JetTypeImpl(
functionType.getAnnotations(),
functionType.getConstructor(),
functionType.isNullable(),
arguments,
((ClassDescriptor) classifier).getMemberScope(arguments)
);
}
@Nullable
private static JetType getFunctionTypeForSamType(@NotNull JetType samType) {
// e.g. samType == Comparator<String>?
ClassifierDescriptor classifier = samType.getConstructor().getDeclarationDescriptor();
if (classifier instanceof ClassDescriptorFromJvmBytecode) {
// Function2<T, T, Int>
JetType functionTypeDefault = ((ClassDescriptorFromJvmBytecode) classifier).getFunctionTypeForSamInterface();
if (functionTypeDefault != null) {
// Function2<String, String, Int>?
JetType substitute = TypeSubstitutor.create(samType).substitute(functionTypeDefault, Variance.INVARIANT);
return substitute == null ? null : fixProjections(TypeUtils.makeNullableAsSpecified(substitute, samType.isNullable()));
}
}
return null;
}
@NotNull
public static JetType getFunctionTypeForAbstractMethod(@NotNull FunctionDescriptor function) {
JetType returnType = function.getReturnType();
assert returnType != null : "function is not initialized: " + function;
List<ValueParameterDescriptor> valueParameters = function.getValueParameters();
List<JetType> parameterTypes = new ArrayList<JetType>(valueParameters.size());
for (ValueParameterDescriptor parameter : valueParameters) {
parameterTypes.add(parameter.getType());
}
return KotlinBuiltIns.getInstance().getFunctionType(
Collections.<AnnotationDescriptor>emptyList(), null, parameterTypes, returnType);
}
private static boolean isSamInterface(@NotNull ClassDescriptor klass) {
if (klass.getKind() != ClassKind.TRAIT) {
return false;
}
List<CallableMemberDescriptor> abstractMembers = getAbstractMembers(klass.getDefaultType());
if (abstractMembers.size() == 1) {
CallableMemberDescriptor member = abstractMembers.get(0);
if (member instanceof SimpleFunctionDescriptor) {
return member.getTypeParameters().isEmpty();
}
}
return false;
}
@NotNull
public static SamConstructorDescriptor createSamConstructorFunction(
@NotNull ClassOrNamespaceDescriptor owner,
@NotNull ClassDescriptorFromJvmBytecode samInterface
) {
assert isSamInterface(samInterface) : samInterface;
SamConstructorDescriptor result = new SamConstructorDescriptor(owner, samInterface);
TypeParameters typeParameters = recreateAndInitializeTypeParameters(samInterface.getTypeConstructor().getParameters(), result);
JetType parameterTypeUnsubstituted = getFunctionTypeForSamType(samInterface.getDefaultType());
assert parameterTypeUnsubstituted != null : "couldn't get function type for SAM type " + samInterface.getDefaultType();
JetType parameterType = typeParameters.substitutor.substitute(parameterTypeUnsubstituted, Variance.IN_VARIANCE);
assert parameterType != null : "couldn't substitute type: " + parameterTypeUnsubstituted +
", substitutor = " + typeParameters.substitutor;
ValueParameterDescriptor parameter = new ValueParameterDescriptorImpl(
result, 0, Collections.<AnnotationDescriptor>emptyList(), Name.identifier("function"), parameterType, false, null);
JetType returnType = typeParameters.substitutor.substitute(samInterface.getDefaultType(), Variance.OUT_VARIANCE);
assert returnType != null : "couldn't substitute type: " + samInterface.getDefaultType() +
", substitutor = " + typeParameters.substitutor;
result.initialize(
null,
null,
typeParameters.descriptors,
Arrays.asList(parameter),
returnType,
Modality.FINAL,
samInterface.getVisibility(),
false
);
return result;
}
public static boolean isSamType(@NotNull JetType type) {
return getFunctionTypeForSamType(type) != null;
}
public static boolean isSamAdapterNecessary(@NotNull FunctionDescriptor fun) {
for (ValueParameterDescriptor param : fun.getValueParameters()) {
if (isSamType(param.getType())) {
return true;
}
}
return false;
}
@NotNull
public static SamAdapterDescriptor<SimpleFunctionDescriptor> createSamAdapterFunction(@NotNull final SimpleFunctionDescriptor original) {
final SamAdapterFunctionDescriptor result = new SamAdapterFunctionDescriptor(original);
return initSamAdapter(original, result, new FunctionInitializer() {
@Override
public void initialize(
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> valueParameters,
@Nullable JetType returnType
) {
result.initialize(
null,
original.getExpectedThisObject(),
typeParameters,
valueParameters,
returnType,
Modality.FINAL,
original.getVisibility(),
false
);
}
});
}
@NotNull
public static SamAdapterDescriptor<ConstructorDescriptor> createSamAdapterConstructor(@NotNull final ConstructorDescriptor original) {
final SamAdapterConstructorDescriptor result = new SamAdapterConstructorDescriptor(original);
return initSamAdapter(original, result, new FunctionInitializer() {
@Override
public void initialize(
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> valueParameters,
@Nullable JetType returnType
) {
result.initialize(
typeParameters,
valueParameters,
original.getVisibility(),
original.getExpectedThisObject() == ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER
);
}
});
}
@NotNull
private static <F extends FunctionDescriptor> SamAdapterDescriptor<F> initSamAdapter(
@NotNull F original,
@NotNull SamAdapterDescriptor<F> adapter,
@NotNull FunctionInitializer initializer
) {
TypeParameters typeParameters = recreateAndInitializeTypeParameters(original.getTypeParameters(), adapter);
JetType returnTypeUnsubstituted = original.getReturnType();
JetType returnType;
if (returnTypeUnsubstituted == null) { // return type may be null for not yet initialized constructors
returnType = null;
}
else {
returnType = typeParameters.substitutor.substitute(returnTypeUnsubstituted, Variance.OUT_VARIANCE);
assert returnType != null : "couldn't substitute type: " + returnTypeUnsubstituted +
", substitutor = " + typeParameters.substitutor;
}
List<ValueParameterDescriptor> originalValueParameters = original.getValueParameters();
List<ValueParameterDescriptor> valueParameters = new ArrayList<ValueParameterDescriptor>(originalValueParameters.size());
for (ValueParameterDescriptor originalParam : originalValueParameters) {
JetType originalType = originalParam.getType();
JetType functionType = getFunctionTypeForSamType(originalType);
JetType newTypeUnsubstituted = functionType != null ? functionType : originalType;
JetType newType = typeParameters.substitutor.substitute(newTypeUnsubstituted, Variance.IN_VARIANCE);
assert newType != null : "couldn't substitute type: " + newTypeUnsubstituted + ", substitutor = " + typeParameters.substitutor;
ValueParameterDescriptor newParam = new ValueParameterDescriptorImpl(
adapter, originalParam.getIndex(), originalParam.getAnnotations(), originalParam.getName(), newType, false, null);
valueParameters.add(newParam);
}
initializer.initialize(typeParameters.descriptors, valueParameters, returnType);
return adapter;
}
@NotNull
private static TypeParameters recreateAndInitializeTypeParameters(
@NotNull List<TypeParameterDescriptor> originalParameters,
@Nullable DeclarationDescriptor newOwner
) {
Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> traitToFunTypeParameters =
DescriptorResolverUtils.recreateTypeParametersAndReturnMapping(originalParameters, newOwner);
TypeSubstitutor typeParametersSubstitutor = DescriptorResolverUtils.createSubstitutorForTypeParameters(traitToFunTypeParameters);
for (Map.Entry<TypeParameterDescriptor, TypeParameterDescriptorImpl> mapEntry : traitToFunTypeParameters.entrySet()) {
TypeParameterDescriptor traitTypeParameter = mapEntry.getKey();
TypeParameterDescriptorImpl funTypeParameter = mapEntry.getValue();
for (JetType upperBound : traitTypeParameter.getUpperBounds()) {
JetType upperBoundSubstituted = typeParametersSubstitutor.substitute(upperBound, Variance.INVARIANT);
assert upperBoundSubstituted != null : "couldn't substitute type: " + upperBound + ", substitutor = " + typeParametersSubstitutor;
funTypeParameter.addUpperBound(upperBoundSubstituted);
}
funTypeParameter.setInitialized();
}
List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(traitToFunTypeParameters.values());
return new TypeParameters(typeParameters, typeParametersSubstitutor);
}
@NotNull
public static SimpleFunctionDescriptor getAbstractMethodOfSamType(@NotNull JetType type) {
return (SimpleFunctionDescriptor) getAbstractMembers(type).get(0);
}
@NotNull
public static SimpleFunctionDescriptor getAbstractMethodOfSamInterface(@NotNull ClassDescriptor samInterface) {
return getAbstractMethodOfSamType(samInterface.getDefaultType());
}
public static boolean isSamInterface(@NotNull JavaClass javaClass) {
return getSamInterfaceMethod(javaClass) != null;
}
// Returns null if not SAM interface
@Nullable
public static JavaMethod getSamInterfaceMethod(@NotNull JavaClass javaClass) {
FqName fqName = javaClass.getFqName();
if (fqName == null || fqName.firstSegmentIs(KotlinBuiltIns.BUILT_INS_PACKAGE_NAME)) {
return null;
}
if (!javaClass.isInterface() || javaClass.isAnnotationType()) {
return null;
}
return findOnlyAbstractMethod(javaClass);
}
@Nullable
private static JavaMethod findOnlyAbstractMethod(@NotNull JavaClass javaClass) {
OnlyAbstractMethodFinder finder = new OnlyAbstractMethodFinder();
if (finder.find(javaClass.getDefaultType())) {
return finder.getFoundMethod();
}
return null;
}
private static class TypeParameters {
public final List<TypeParameterDescriptor> descriptors;
public final TypeSubstitutor substitutor;
private TypeParameters(List<TypeParameterDescriptor> descriptors, TypeSubstitutor substitutor) {
this.descriptors = descriptors;
this.substitutor = substitutor;
}
}
private static abstract class FunctionInitializer {
public abstract void initialize(
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> valueParameters,
@Nullable JetType returnType
);
}
private static class OnlyAbstractMethodFinder {
private JavaMethod foundMethod;
private JavaTypeSubstitutor foundClassSubstitutor;
private boolean find(@NotNull JavaClassifierType classifierType) {
JavaTypeSubstitutor classSubstitutor = classifierType.getSubstitutor();
JavaClassifier classifier = classifierType.getClassifier();
if (classifier == null) {
return false; // can't resolve class -> not a SAM interface
}
assert classifier instanceof JavaClass : "Classifier should be a class here: " + classifier;
JavaClass javaClass = (JavaClass) classifier;
if (JavaSupertypeResolver.OBJECT_FQ_NAME.equals(javaClass.getFqName())) {
return true;
}
for (JavaMethod method : javaClass.getMethods()) {
if (DescriptorResolverUtils.isObjectMethod(method)) { // e.g., ignore toString() declared in interface
continue;
}
if (!method.getTypeParameters().isEmpty()) {
return false; // if interface has generic methods, it is not a SAM interface
}
if (foundMethod == null) {
foundMethod = method;
foundClassSubstitutor = classSubstitutor;
continue;
}
if (!areSignaturesErasureEqual(method, classSubstitutor, foundMethod, foundClassSubstitutor)) {
return false; // different signatures
}
}
for (JavaClassifierType t : classifierType.getSupertypes()) {
if (!find(t)) {
return false;
}
}
return true;
}
/**
* @see com.intellij.psi.util.MethodSignatureUtil#areSignaturesErasureEqual
*/
private static boolean areSignaturesErasureEqual(
@NotNull JavaMethod method1,
@NotNull JavaTypeSubstitutor substitutor1,
@NotNull JavaMethod method2,
@NotNull JavaTypeSubstitutor substitutor2
) {
if (method1.isConstructor() != method2.isConstructor()) return false;
if (!method1.isConstructor() && !method1.getName().equals(method2.getName())) return false;
if (method1.isVararg() != method2.isVararg()) return false;
Collection<JavaValueParameter> parameters1 = method1.getValueParameters();
Collection<JavaValueParameter> parameters2 = method2.getValueParameters();
if (parameters1.size() != parameters2.size()) return false;
for (Iterator<JavaValueParameter> it1 = parameters1.iterator(), it2 = parameters2.iterator(); it1.hasNext(); ) {
JavaType type1 = erasure(substitutor1.substitute(it1.next().getType()), substitutor1);
JavaType type2 = erasure(substitutor2.substitute(it2.next().getType()), substitutor2);
if (!(type1 == null ? type2 == null : type1.equals(type2))) return false;
}
return true;
}
@Nullable
private JavaMethod getFoundMethod() {
return foundMethod;
}
}
}
@@ -1,173 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.scope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.java.resolver.JavaMemberResolver;
import org.jetbrains.jet.lang.resolve.java.resolver.ProgressChecker;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl;
import java.util.*;
public abstract class JavaBaseScope extends JetScopeImpl {
@NotNull
protected final JavaMemberResolver memberResolver;
@NotNull
protected final MembersProvider membersProvider;
@NotNull
private final Map<Name, Set<FunctionDescriptor>> functionDescriptors = new HashMap<Name, Set<FunctionDescriptor>>();
@NotNull
private final Map<Name, Set<VariableDescriptor>> propertyDescriptors = new HashMap<Name, Set<VariableDescriptor>>();
@Nullable
private Collection<DeclarationDescriptor> allDescriptors = null;
@Nullable
private Set<ClassDescriptor> objectDescriptors = null;
@NotNull
protected final ClassOrNamespaceDescriptor descriptor;
private Collection<ClassDescriptor> innerClasses = null;
protected JavaBaseScope(
@NotNull ClassOrNamespaceDescriptor descriptor,
@NotNull JavaMemberResolver memberResolver,
@NotNull MembersProvider membersProvider
) {
this.memberResolver = memberResolver;
this.membersProvider = membersProvider;
this.descriptor = descriptor;
}
@NotNull
@Override
public DeclarationDescriptor getContainingDeclaration() {
return descriptor;
}
@NotNull
@Override
public Collection<VariableDescriptor> getProperties(@NotNull Name name) {
Set<VariableDescriptor> cached = propertyDescriptors.get(name);
if (cached != null) return cached;
if (allDescriptorsComputed()) {
return Collections.emptySet();
}
Set<VariableDescriptor> computedDescriptors = computePropertyDescriptors(name);
propertyDescriptors.put(name, computedDescriptors);
return computedDescriptors;
}
@NotNull
private Set<VariableDescriptor> computePropertyDescriptors(@NotNull Name name) {
NamedMembers members = membersProvider.get(name);
if (members == null) {
return Collections.emptySet();
}
return memberResolver.resolveFieldGroup(members, descriptor);
}
@NotNull
@Override
public Collection<FunctionDescriptor> getFunctions(@NotNull Name name) {
Set<FunctionDescriptor> cached = functionDescriptors.get(name);
if (cached != null) return cached;
if (allDescriptorsComputed()) {
return Collections.emptySet();
}
Set<FunctionDescriptor> computedDescriptors = computeFunctionDescriptor(name);
functionDescriptors.put(name, computedDescriptors);
return computedDescriptors;
}
@NotNull
protected abstract Set<FunctionDescriptor> computeFunctionDescriptor(@NotNull Name name);
@NotNull
@Override
public Collection<DeclarationDescriptor> getAllDescriptors() {
if (allDescriptorsComputed()) {
return allDescriptors;
}
allDescriptors = computeAllDescriptors();
return allDescriptors;
}
private boolean allDescriptorsComputed() {
return allDescriptors != null;
}
@NotNull
protected Collection<DeclarationDescriptor> computeAllDescriptors() {
Collection<DeclarationDescriptor> result = new HashSet<DeclarationDescriptor>();
result.addAll(computeFieldAndFunctionDescriptors());
result.addAll(filterObjects(getInnerClasses(), false));
return result;
}
@NotNull
@Override
public Set<ClassDescriptor> getObjectDescriptors() {
if (objectDescriptors == null) {
objectDescriptors = new HashSet<ClassDescriptor>(filterObjects(getInnerClasses(), true));
}
return objectDescriptors;
}
@NotNull
protected abstract Collection<ClassDescriptor> computeInnerClasses();
@NotNull
private Collection<DeclarationDescriptor> computeFieldAndFunctionDescriptors() {
Collection<DeclarationDescriptor> result = new ArrayList<DeclarationDescriptor>();
for (NamedMembers members : membersProvider.allMembers()) {
Name name = members.getName();
ProgressChecker.getInstance().checkCanceled();
result.addAll(getFunctions(name));
ProgressChecker.getInstance().checkCanceled();
result.addAll(getProperties(name));
}
return result;
}
@NotNull
protected Collection<ClassDescriptor> getInnerClasses() {
if (innerClasses == null) {
innerClasses = computeInnerClasses();
}
return innerClasses;
}
@NotNull
private static Collection<ClassDescriptor> filterObjects(@NotNull Collection<ClassDescriptor> classes, boolean objects) {
List<ClassDescriptor> result = new ArrayList<ClassDescriptor>();
for (ClassDescriptor descriptor : classes) {
if (descriptor.getKind().isObject() == objects) {
result.add(descriptor);
}
}
return result;
}
}
@@ -1,84 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.scope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.java.resolver.JavaMemberResolver;
import org.jetbrains.jet.lang.resolve.name.LabelName;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.*;
public abstract class JavaClassMembersScope extends JavaBaseScope {
private Map<Name, ClassDescriptor> innerClassesMap = null;
protected JavaClassMembersScope(
@NotNull ClassOrNamespaceDescriptor descriptor,
@NotNull MembersProvider membersProvider,
@NotNull JavaMemberResolver memberResolver
) {
super(descriptor, memberResolver, membersProvider);
}
@NotNull
@Override
public Collection<DeclarationDescriptor> getDeclarationsByLabel(LabelName labelName) {
throw new UnsupportedOperationException(); // TODO
}
@NotNull
@Override
protected Set<FunctionDescriptor> computeFunctionDescriptor(@NotNull Name name) {
NamedMembers members = membersProvider.get(name);
if (members == null) {
return Collections.emptySet();
}
return memberResolver.resolveFunctionGroupForClass(members, descriptor);
}
@NotNull
private Map<Name, ClassDescriptor> getInnerClassesMap() {
if (innerClassesMap == null) {
Collection<ClassDescriptor> innerClasses = getInnerClasses();
innerClassesMap = new HashMap<Name, ClassDescriptor>();
for (ClassDescriptor innerClass : innerClasses) {
innerClassesMap.put(innerClass.getName(), innerClass);
}
}
return innerClassesMap;
}
@Override
public ClassDescriptor getObjectDescriptor(@NotNull Name name) {
ClassDescriptor innerClass = getInnerClassesMap().get(name);
if (innerClass != null && innerClass.getKind().isObject()) {
return innerClass;
}
return null;
}
@Override
public ClassifierDescriptor getClassifier(@NotNull Name name) {
ClassDescriptor innerClass = getInnerClassesMap().get(name);
if (innerClass == null || innerClass.getKind().isObject()) {
return null;
}
return innerClass;
}
}
@@ -1,107 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.scope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
import org.jetbrains.jet.lang.resolve.java.resolver.JavaMemberResolver;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.name.FqName;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.IGNORE_KOTLIN_SOURCES;
public final class JavaClassNonStaticMembersScope extends JavaClassMembersScope {
private Collection<ConstructorDescriptor> constructors = null;
private ConstructorDescriptor primaryConstructor = null;
@NotNull
private final ClassDescriptor descriptor;
@NotNull
private final JavaClass javaClass;
private final boolean staticMembersOfPsiClass;
public JavaClassNonStaticMembersScope(
@NotNull ClassDescriptor descriptor,
@NotNull JavaClass javaClass,
boolean staticMembersOfClass,
@NotNull JavaMemberResolver memberResolver
) {
super(descriptor, MembersProvider.forClass(javaClass, staticMembersOfClass), memberResolver);
this.descriptor = descriptor;
this.javaClass = javaClass;
this.staticMembersOfPsiClass = staticMembersOfClass;
}
@NotNull
public Collection<ConstructorDescriptor> getConstructors() {
initConstructorsIfNeeded();
return constructors;
}
@Nullable
public ConstructorDescriptor getPrimaryConstructor() {
initConstructorsIfNeeded();
return primaryConstructor;
}
private void initConstructorsIfNeeded() {
if (constructors == null) {
constructors = memberResolver.resolveConstructors(javaClass, descriptor);
for (ConstructorDescriptor constructor : constructors) {
if (constructor.isPrimary()) {
if (primaryConstructor != null) {
throw new IllegalStateException(
"Class has more than one primary constructor: " + primaryConstructor + "\n" + constructor);
}
primaryConstructor = constructor;
}
}
}
}
@NotNull
@Override
protected Collection<ClassDescriptor> computeInnerClasses() {
if (staticMembersOfPsiClass) {
return Collections.emptyList();
}
Collection<JavaClass> innerClasses = javaClass.getInnerClasses();
List<ClassDescriptor> result = new ArrayList<ClassDescriptor>(innerClasses.size());
for (JavaClass innerClass : innerClasses) {
result.add(resolveInnerClass(innerClass));
}
return result;
}
@NotNull
private ClassDescriptor resolveInnerClass(@NotNull JavaClass innerClass) {
FqName fqName = innerClass.getFqName();
assert fqName != null : "Inner class has no qualified name: " + innerClass;
ClassDescriptor classDescriptor = memberResolver.resolveClass(fqName, IGNORE_KOTLIN_SOURCES);
assert classDescriptor != null : "Couldn't resolve inner class " + fqName;
return classDescriptor;
}
}
@@ -1,73 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.scope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.java.resolver.JavaMemberResolver;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.Collection;
import java.util.Collections;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.INCLUDE_KOTLIN_SOURCES;
public final class JavaClassStaticMembersScope extends JavaClassMembersScope {
@NotNull
private final FqName packageFQN;
@NotNull
private final JavaClass javaClass;
public JavaClassStaticMembersScope(
@NotNull NamespaceDescriptor descriptor,
@NotNull FqName packageFQN,
@NotNull JavaClass javaClass,
@NotNull JavaMemberResolver memberResolver
) {
super(descriptor, MembersProvider.forClass(javaClass, true), memberResolver);
this.packageFQN = packageFQN;
this.javaClass = javaClass;
}
@Override
public NamespaceDescriptor getNamespace(@NotNull Name name) {
return memberResolver.resolveNamespace(packageFQN.child(name), INCLUDE_KOTLIN_SOURCES);
}
@NotNull
@Override
protected Collection<DeclarationDescriptor> computeAllDescriptors() {
Collection<DeclarationDescriptor> result = super.computeAllDescriptors();
for (JavaClass nested : javaClass.getInnerClasses()) {
NamespaceDescriptor namespace = getNamespace(nested.getName());
if (namespace != null) {
result.add(namespace);
}
}
return result;
}
@NotNull
@Override
protected Collection<ClassDescriptor> computeInnerClasses() {
return Collections.emptyList();
}
}
@@ -1,143 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.scope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptor;
import org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils;
import org.jetbrains.jet.lang.resolve.java.resolver.JavaFunctionResolver;
import org.jetbrains.jet.lang.resolve.java.resolver.JavaMemberResolver;
import org.jetbrains.jet.lang.resolve.java.resolver.ProgressChecker;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.java.structure.JavaPackage;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.IGNORE_KOTLIN_SOURCES;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.INCLUDE_KOTLIN_SOURCES;
public final class JavaPackageScope extends JavaBaseScope {
@NotNull
private final JavaPackage javaPackage;
@NotNull
private final FqName packageFQN;
public JavaPackageScope(
@NotNull NamespaceDescriptor descriptor,
@NotNull JavaPackage javaPackage,
@NotNull FqName packageFQN,
@NotNull JavaMemberResolver memberResolver
) {
super(descriptor, memberResolver, MembersProvider.forPackage(javaPackage));
this.javaPackage = javaPackage;
this.packageFQN = packageFQN;
}
@Override
public ClassifierDescriptor getClassifier(@NotNull Name name) {
ClassDescriptor classDescriptor = memberResolver.resolveClass(packageFQN.child(name), IGNORE_KOTLIN_SOURCES);
if (classDescriptor == null || classDescriptor.getKind().isObject()) {
return null;
}
return classDescriptor;
}
@Override
public ClassDescriptor getObjectDescriptor(@NotNull Name name) {
ClassDescriptor classDescriptor = memberResolver.resolveClass(packageFQN.child(name), IGNORE_KOTLIN_SOURCES);
if (classDescriptor != null && classDescriptor.getKind().isObject()) {
return classDescriptor;
}
return null;
}
@Override
public NamespaceDescriptor getNamespace(@NotNull Name name) {
return memberResolver.resolveNamespace(packageFQN.child(name), INCLUDE_KOTLIN_SOURCES);
}
@NotNull
@Override
protected Collection<DeclarationDescriptor> computeAllDescriptors() {
Collection<DeclarationDescriptor> result = super.computeAllDescriptors();
result.addAll(computeAllPackageDeclarations());
return result;
}
@NotNull
private Collection<DeclarationDescriptor> computeAllPackageDeclarations() {
Collection<DeclarationDescriptor> result = new HashSet<DeclarationDescriptor>();
for (JavaPackage subPackage : javaPackage.getSubPackages()) {
NamespaceDescriptor childNs = memberResolver.resolveNamespace(subPackage.getFqName(), IGNORE_KOTLIN_SOURCES);
if (childNs != null) {
result.add(childNs);
}
}
for (JavaClass javaClass : DescriptorResolverUtils.getClassesInPackage(javaPackage)) {
if (DescriptorResolverUtils.isCompiledKotlinPackageClass(javaClass)) continue;
if (javaClass.getOriginKind() == JavaClass.OriginKind.KOTLIN_LIGHT_CLASS) continue;
if (javaClass.getVisibility() != Visibilities.PUBLIC) continue;
ProgressChecker.getInstance().checkCanceled();
FqName fqName = javaClass.getFqName();
if (fqName == null) continue;
ClassDescriptor classDescriptor = memberResolver.resolveClass(fqName, IGNORE_KOTLIN_SOURCES);
if (classDescriptor != null) {
result.add(classDescriptor);
}
NamespaceDescriptor namespace = memberResolver.resolveNamespace(fqName, IGNORE_KOTLIN_SOURCES);
if (namespace != null) {
result.add(namespace);
}
}
return result;
}
@Override
@NotNull
protected Set<FunctionDescriptor> computeFunctionDescriptor(@NotNull Name name) {
NamedMembers members = membersProvider.get(name);
if (members == null) {
return Collections.emptySet();
}
SamConstructorDescriptor samConstructor = JavaFunctionResolver.resolveSamConstructor((NamespaceDescriptor) descriptor, members);
if (samConstructor == null) {
return Collections.emptySet();
}
return Collections.<FunctionDescriptor>singleton(samConstructor);
}
@NotNull
@Override
protected Collection<ClassDescriptor> computeInnerClasses() {
return Collections.emptyList();
}
}
@@ -1,251 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.scope;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.Visibilities;
import org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils;
import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils;
import org.jetbrains.jet.lang.resolve.java.structure.*;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/* package */ final class MembersCache {
private final Multimap<Name, Runnable> memberProcessingTasks = HashMultimap.create();
private final Map<Name, NamedMembers> namedMembersMap = new HashMap<Name, NamedMembers>();
@Nullable
public NamedMembers get(@NotNull Name name) {
runTasksByName(name);
return namedMembersMap.get(name);
}
@NotNull
public Collection<NamedMembers> allMembers() {
runAllTasks();
memberProcessingTasks.clear();
return namedMembersMap.values();
}
@NotNull
private NamedMembers getOrCreateEmpty(@NotNull JavaNamedElement element) {
Name name = element.getName();
NamedMembers r = namedMembersMap.get(name);
if (r == null) {
r = new NamedMembers(name);
namedMembersMap.put(name, r);
}
return r;
}
private void addTask(@NotNull JavaNamedElement member, @NotNull RunOnce task) {
memberProcessingTasks.put(member.getName(), task);
}
private void runTasksByName(Name name) {
if (!memberProcessingTasks.containsKey(name)) return;
Collection<Runnable> tasks = memberProcessingTasks.get(name);
for (Runnable task : tasks) {
task.run();
}
// Delete tasks
tasks.clear();
}
private void runAllTasks() {
for (Runnable task : memberProcessingTasks.values()) {
task.run();
}
}
@NotNull
public static MembersCache buildForClass(@NotNull JavaClass javaClass, boolean staticMembers) {
MembersCache membersCache = new MembersCache();
membersCache.new ClassMemberProcessor(javaClass, staticMembers).process();
membersCache.new ExtraPackageMembersProcessor(javaClass.getInnerClasses()).process();
return membersCache;
}
@NotNull
public static MembersCache buildForPackage(@NotNull JavaPackage javaPackage) {
MembersCache membersCache = new MembersCache();
Collection<JavaClass> classes = DescriptorResolverUtils.getClassesInPackage(javaPackage);
membersCache.new ExtraPackageMembersProcessor(classes).process();
return membersCache;
}
private class ExtraPackageMembersProcessor { // 'extra' means that PSI elements for these members are not just top-level classes
@NotNull
private final Collection<JavaClass> javaClasses;
private ExtraPackageMembersProcessor(@NotNull Collection<JavaClass> javaClasses) {
this.javaClasses = javaClasses;
}
private void process() {
for (JavaClass javaClass : javaClasses) {
if (javaClass.getOriginKind() != JavaClass.OriginKind.KOTLIN_LIGHT_CLASS) {
if (SingleAbstractMethodUtils.isSamInterface(javaClass)) {
processSamInterface(javaClass);
}
}
}
}
private void processSamInterface(@NotNull JavaClass javaClass) {
getOrCreateEmpty(javaClass).setSamInterface(javaClass);
}
}
private class ClassMemberProcessor {
@NotNull
private final JavaClass javaClass;
private final boolean staticMembers;
private ClassMemberProcessor(@NotNull JavaClass javaClass, boolean staticMembers) {
this.javaClass = javaClass;
this.staticMembers = staticMembers;
}
private void process() {
processFields();
processMethods();
processNestedClasses();
}
private void processFields() {
for (final JavaField field : javaClass.getAllFields()) {
addTask(field, new RunOnce() {
@Override
public void doRun() {
processField(field);
}
});
}
}
private void processMethods() {
createEntriesForAllMethods();
processOwnMethods();
}
private void createEntriesForAllMethods() {
for (JavaMethod method : javaClass.getAllMethods()) {
getOrCreateEmpty(method);
}
}
private void processOwnMethods() {
for (final JavaMethod method : javaClass.getMethods()) {
addTask(method, new RunOnce() {
@Override
public void doRun() {
processOwnMethod(method);
}
});
}
}
private void processNestedClasses() {
if (!staticMembers) {
return;
}
for (final JavaClass nested : javaClass.getInnerClasses()) {
addTask(nested, new RunOnce() {
@Override
public void doRun() {
processNestedClass(nested);
}
});
}
}
private boolean includeMember(@NotNull JavaMember member) {
if (javaClass.isEnum() && staticMembers) {
return member.isStatic();
}
if (member.isStatic() != staticMembers) {
return false;
}
if (!isInCurrentClass(member)) {
return false;
}
if (member.getVisibility() == Visibilities.PRIVATE) {
return false;
}
if (DescriptorResolverUtils.isObjectMethodInInterface(member)) {
return false;
}
return true;
}
private boolean isInCurrentClass(@NotNull JavaMember member) {
FqName fqName = member.getContainingClass().getFqName();
return fqName != null && fqName.equals(javaClass.getFqName());
}
private void processField(@NotNull JavaField field) {
// group must be created even for excluded field
NamedMembers namedMembers = getOrCreateEmpty(field);
if (includeMember(field)) {
namedMembers.addField(field);
}
}
private void processOwnMethod(@NotNull JavaMethod ownMethod) {
if (includeMember(ownMethod)) {
getOrCreateEmpty(ownMethod).addMethod(ownMethod);
}
}
private void processNestedClass(@NotNull JavaClass nested) {
if (SingleAbstractMethodUtils.isSamInterface(nested)) {
getOrCreateEmpty(nested).setSamInterface(nested);
}
}
}
private static abstract class RunOnce implements Runnable {
private boolean hasRun = false;
@Override
public final void run() {
if (hasRun) return;
hasRun = true;
doRun();
}
protected abstract void doRun();
}
}
@@ -1,77 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.scope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.java.structure.JavaPackage;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.Collection;
/* package */ class MembersProvider {
@Nullable
private final JavaClass javaClass;
@Nullable
private final JavaPackage javaPackage;
private final boolean staticMembers;
private MembersCache membersCache;
private MembersProvider(@Nullable JavaClass javaClass, @Nullable JavaPackage javaPackage, boolean staticMembers) {
this.javaClass = javaClass;
this.javaPackage = javaPackage;
this.staticMembers = staticMembers;
}
@NotNull
public static MembersProvider forPackage(@NotNull JavaPackage javaPackage) {
return new MembersProvider(null, javaPackage, true);
}
@NotNull
public static MembersProvider forClass(@NotNull JavaClass javaClass, boolean staticMembers) {
return new MembersProvider(javaClass, null, staticMembers);
}
@Nullable
public NamedMembers get(@NotNull Name name) {
return getMembersCache().get(name);
}
@NotNull
public Collection<NamedMembers> allMembers() {
return getMembersCache().allMembers();
}
@NotNull
private MembersCache getMembersCache() {
if (membersCache == null) {
if (javaClass != null) {
membersCache = MembersCache.buildForClass(javaClass, staticMembers);
}
else if (javaPackage != null) {
membersCache = MembersCache.buildForPackage(javaPackage);
}
else {
throw new IllegalStateException("MembersProvider should be created either for a class or for a package");
}
}
return membersCache;
}
}
@@ -1,78 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.scope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.java.structure.JavaField;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.ArrayList;
import java.util.List;
public final class NamedMembers {
public NamedMembers(@NotNull Name name) {
this.name = name;
}
@NotNull
private final Name name;
@NotNull
private final List<JavaMethod> methods = new ArrayList<JavaMethod>();
@NotNull
private final List<JavaField> fields = new ArrayList<JavaField>();
@Nullable
private JavaClass samInterface;
void addMethod(@NotNull JavaMethod method) {
methods.add(method);
}
void addField(@NotNull JavaField field) {
fields.add(field);
}
void setSamInterface(@NotNull JavaClass samInterface) {
this.samInterface = samInterface;
}
@NotNull
public Name getName() {
return name;
}
@NotNull
public List<JavaMethod> getMethods() {
return methods;
}
@NotNull
public List<JavaField> getFields() {
return fields;
}
@Nullable
public JavaClass getSamInterface() {
return samInterface;
}
}
@@ -1,35 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.Collection;
public interface JavaAnnotation extends JavaElement {
@Nullable
JavaAnnotationArgument findArgument(@NotNull Name name);
@NotNull
Collection<JavaAnnotationArgument> getArguments();
@Nullable
FqName getFqName();
}
@@ -1,25 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.name.Name;
public interface JavaAnnotationArgument extends JavaElement {
@Nullable
Name getName();
}
@@ -1,24 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
public interface JavaAnnotationAsAnnotationArgument extends JavaAnnotationArgument {
@NotNull
JavaAnnotation getAnnotation();
}
@@ -1,31 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.name.FqName;
import java.util.Collection;
public interface JavaAnnotationOwner extends JavaElement {
@NotNull
Collection<JavaAnnotation> getAnnotations();
@Nullable
JavaAnnotation findAnnotation(@NotNull FqName fqName);
}
@@ -1,26 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
public interface JavaArrayAnnotationArgument extends JavaAnnotationArgument {
@NotNull
Collection<JavaAnnotationArgument> getElements();
}
@@ -1,24 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
public interface JavaArrayType extends JavaType {
@NotNull
JavaType getComponentType();
}
@@ -1,70 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.name.FqName;
import java.util.Collection;
public interface JavaClass extends JavaClassifier, JavaTypeParameterListOwner, JavaModifierListOwner, JavaAnnotationOwner {
@NotNull
Collection<JavaClass> getInnerClasses();
@Nullable
FqName getFqName();
boolean isInterface();
boolean isAnnotationType();
boolean isEnum();
@Nullable
JavaClass getOuterClass();
@NotNull
Collection<JavaClassifierType> getSupertypes();
@NotNull
Collection<JavaMethod> getMethods();
@NotNull
Collection<JavaMethod> getAllMethods();
@NotNull
Collection<JavaField> getFields();
@NotNull
Collection<JavaField> getAllFields();
@NotNull
Collection<JavaMethod> getConstructors();
@NotNull
JavaClassifierType getDefaultType();
@NotNull
OriginKind getOriginKind();
enum OriginKind {
COMPILED,
SOURCE,
KOTLIN_LIGHT_CLASS
}
}
@@ -1,20 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
public interface JavaClassifier extends JavaNamedElement {
}
@@ -1,41 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
public interface JavaClassifierType extends JavaType {
@Nullable
JavaClassifier getClassifier();
@NotNull
JavaTypeSubstitutor getSubstitutor();
@NotNull
Collection<JavaClassifierType> getSupertypes();
@NotNull
String getPresentableText();
boolean isRaw();
@NotNull
Collection<JavaType> getTypeArguments();
}
@@ -1,20 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
public interface JavaElement {
}
@@ -1,40 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
import java.util.ServiceLoader;
public abstract class JavaElementFactory {
private static JavaElementFactory instance;
@NotNull
public static JavaElementFactory getInstance() {
if (instance == null) {
Iterator<JavaElementFactory> iterator =
ServiceLoader.load(JavaElementFactory.class, JavaElementFactory.class.getClassLoader()).iterator();
assert iterator.hasNext() : "No service found: " + JavaElementFactory.class.getName();
instance = iterator.next();
}
return instance;
}
@NotNull
public abstract JavaArrayType createArrayType(@NotNull JavaType elementType);
}
@@ -1,26 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
public interface JavaField extends JavaMember {
boolean isEnumEntry();
@NotNull
JavaType getType();
}
@@ -1,24 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.Nullable;
public interface JavaLiteralAnnotationArgument extends JavaAnnotationArgument {
@Nullable
Object getValue();
}
@@ -1,24 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
public interface JavaMember extends JavaModifierListOwner, JavaAnnotationOwner, JavaNamedElement {
@NotNull
JavaClass getContainingClass();
}
@@ -1,36 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
public interface JavaMethod extends JavaMember, JavaTypeParameterListOwner {
@NotNull
Collection<JavaValueParameter> getValueParameters();
boolean hasAnnotationParameterDefaultValue();
@Nullable
JavaType getReturnType();
boolean isVararg();
boolean isConstructor();
}
@@ -1,31 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.Visibility;
public interface JavaModifierListOwner extends JavaElement {
boolean isAbstract();
boolean isStatic();
boolean isFinal();
@NotNull
Visibility getVisibility();
}
@@ -1,25 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.name.Name;
public interface JavaNamedElement extends JavaElement {
@NotNull
Name getName();
}
@@ -1,37 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.name.FqName;
import java.util.Collection;
public interface JavaPackage extends JavaElement {
/**
* NOTE: do not use this method directly
* @see org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils#getClassesInPackage(JavaPackage)
*/
@NotNull
Collection<JavaClass> getClasses();
@NotNull
Collection<JavaPackage> getSubPackages();
@NotNull
FqName getFqName();
}
@@ -1,24 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
public interface JavaPrimitiveType extends JavaType {
@NotNull
String getCanonicalText();
}
@@ -1,24 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.Nullable;
public interface JavaReferenceAnnotationArgument extends JavaAnnotationArgument {
@Nullable
JavaElement resolve();
}
@@ -1,52 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
import java.util.ServiceLoader;
public abstract class JavaSignatureFormatter {
private static JavaSignatureFormatter instance;
@NotNull
public static JavaSignatureFormatter getInstance() {
if (instance == null) {
Iterator<JavaSignatureFormatter> iterator =
ServiceLoader.load(JavaSignatureFormatter.class, JavaSignatureFormatter.class.getClassLoader()).iterator();
assert iterator.hasNext() : "No service found: " + JavaSignatureFormatter.class.getName();
instance = iterator.next();
}
return instance;
}
/**
* @return a formatted signature of a method, showing method name and fully qualified names of its parameter types, e.g.:
* {@code "foo(double, java.lang.String)"}
*/
@NotNull
public abstract String formatMethod(@NotNull JavaMethod method);
/**
* @return a formatted signature of a method, showing method's containing class, return type and parameter types, all names are fully
* qualified, e.g.:
* {@code "java.lang.Class boolean isAnnotationPresent(java.lang.Class&lt;? extends java.lang.annotation.Annotation&gt;)"}
*/
@NotNull
public abstract String getExternalName(@NotNull JavaMethod method);
}
@@ -1,20 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
public interface JavaType {
}
@@ -1,38 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
public interface JavaTypeParameter extends JavaClassifier {
int getIndex();
@NotNull
Collection<JavaClassifierType> getUpperBounds();
@Nullable
JavaTypeParameterListOwner getOwner();
@NotNull
JavaType getType();
@NotNull
JavaTypeProvider getTypeProvider();
}
@@ -1,26 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
public interface JavaTypeParameterListOwner extends JavaElement {
@NotNull
Collection<JavaTypeParameter> getTypeParameters();
}
@@ -1,24 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
public interface JavaTypeProvider {
@NotNull
JavaType createJavaLangObjectType();
}
@@ -1,59 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.Map;
public interface JavaTypeSubstitutor {
JavaTypeSubstitutor EMPTY = new JavaTypeSubstitutor() {
@NotNull
@Override
public JavaType substitute(@NotNull JavaType type) {
return type;
}
@Nullable
@Override
public JavaType substitute(@NotNull JavaTypeParameter typeParameter) {
return typeParameter.getType();
}
@NotNull
@Override
public Map<JavaTypeParameter, JavaType> getSubstitutionMap() {
return Collections.emptyMap();
}
@Override
public String toString() {
return "Empty JavaTypeSubstitutor";
}
};
@NotNull
JavaType substitute(@NotNull JavaType type);
@Nullable
JavaType substitute(@NotNull JavaTypeParameter typeParameter);
@NotNull
Map<JavaTypeParameter, JavaType> getSubstitutionMap();
}
@@ -1,31 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.name.Name;
public interface JavaValueParameter extends JavaAnnotationOwner {
@Nullable
Name getName();
@NotNull
JavaType getType();
boolean isVararg();
}
@@ -1,30 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface JavaWildcardType extends JavaType {
@Nullable
JavaType getBound();
boolean isExtends();
@NotNull
JavaTypeProvider getTypeProvider();
}
@@ -1,72 +0,0 @@
package org.jetbrains.jet.lang.resolve.java.vfilefinder;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.cli.jvm.compiler.ClassPath;
import org.jetbrains.jet.lang.resolve.java.resolver.KotlinClassFileHeader;
import org.jetbrains.jet.lang.resolve.name.FqName;
public class CliVirtualFileFinder implements VirtualFileFinder {
@NotNull
private final ClassPath classPath;
public CliVirtualFileFinder(@NotNull ClassPath path) {
classPath = path;
}
@Nullable
@Override
public VirtualFile find(@NotNull FqName className, @NotNull GlobalSearchScope scope) {
//TODO: use scope
return find(className);
}
@Nullable
@Override
public VirtualFile find(@NotNull FqName className) {
for (VirtualFile root : classPath) {
VirtualFile fileInRoot = findFileInRoot(className.asString(), root);
if (fileInRoot != null) {
return fileInRoot;
}
}
return null;
}
//NOTE: copied with some changes from CoreJavaFileManager
@Nullable
private static VirtualFile findFileInRoot(@NotNull String qName, @NotNull VirtualFile root) {
String pathRest = qName;
VirtualFile cur = root;
while (true) {
int dot = pathRest.indexOf('.');
if (dot < 0) break;
String pathComponent = pathRest.substring(0, dot);
VirtualFile child = cur.findChild(pathComponent);
if (child == null) break;
pathRest = pathRest.substring(dot + 1);
cur = child;
}
String className = pathRest.replace('.', '$');
VirtualFile vFile = cur.findChild(className + ".class");
if (vFile != null) {
if (!vFile.isValid()) {
//TODO: log
return null;
}
//NOTE: currently we use VirtualFileFinder to find Kotlin binaries only
if (KotlinClassFileHeader.readKotlinHeaderFromClassFile(vFile).getType() != KotlinClassFileHeader.HeaderType.NONE) {
return vFile;
}
}
return null;
}
}
@@ -1,17 +0,0 @@
package org.jetbrains.jet.lang.resolve.java.vfilefinder;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.name.FqName;
public interface VirtualFileFinder {
@Nullable
VirtualFile find(@NotNull FqName className, @NotNull GlobalSearchScope scope);
//NOTE: uses all scope by default
//TODO: should be removed, scope should always be passed
@Nullable
VirtualFile find(@NotNull FqName className);
}