read properties from binary classes
(intermediate version)
This commit is contained in:
@@ -16,6 +16,7 @@ import org.jetbrains.jet.lang.resolve.calls.*;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaNamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
|
||||
@@ -2597,10 +2598,10 @@ If finally block is present, its last expression is the value of try expression.
|
||||
genTypeInfoToProjection(v, argument.getProjectionKind());
|
||||
v.astore(TYPE_OBJECT);
|
||||
}
|
||||
v.invokestatic("jet/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/TypeInfo;");
|
||||
v.invokestatic("jet/TypeInfo", JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD, "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/TypeInfo;");
|
||||
}
|
||||
else {
|
||||
v.invokestatic("jet/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/TypeInfo;");
|
||||
v.invokestatic("jet/TypeInfo", JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD, "(Ljava/lang/Class;Z)Ljet/TypeInfo;");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2654,7 +2655,7 @@ If finally block is present, its last expression is the value of try expression.
|
||||
}
|
||||
else {
|
||||
v.load(0, TYPE_OBJECT);
|
||||
v.invokeinterface(TYPE_JET_OBJECT.getInternalName(), "getTypeInfo", "()Ljet/TypeInfo;");
|
||||
v.invokeinterface(TYPE_JET_OBJECT.getInternalName(), JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD, "()Ljet/TypeInfo;");
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -2663,7 +2664,7 @@ If finally block is present, its last expression is the value of try expression.
|
||||
descriptor = CodegenUtil.getOuterClassDescriptor(descriptor);
|
||||
v.invokeinterface(TYPE_JET_OBJECT.getInternalName(), "getOuterObject", "()Ljet/JetObject;");
|
||||
}
|
||||
v.invokeinterface(TYPE_JET_OBJECT.getInternalName(), "getTypeInfo", "()Ljet/TypeInfo;");
|
||||
v.invokeinterface(TYPE_JET_OBJECT.getInternalName(), JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD, "()Ljet/TypeInfo;");
|
||||
}
|
||||
v.aconst(ownerType);
|
||||
v.iconst(typeParameterDescriptor.getIndex());
|
||||
|
||||
@@ -240,6 +240,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod();
|
||||
Method originalMethod = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION).getAsmMethod();
|
||||
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
|
||||
mv.visitAnnotation(JvmStdlibNames.JET_PROPERTY.getDescriptor(), true).visitEnd();
|
||||
InstructionAdapter iv = null;
|
||||
if (v.generateCode()) {
|
||||
mv.visitCode();
|
||||
@@ -259,6 +260,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod();
|
||||
originalMethod = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION).getAsmMethod();
|
||||
mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
|
||||
mv.visitAnnotation(JvmStdlibNames.JET_PROPERTY.getDescriptor(), true).visitEnd();
|
||||
if (v.generateCode()) {
|
||||
mv.visitCode();
|
||||
|
||||
@@ -838,7 +840,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
if(!CodegenUtil.hasDerivedTypeInfoField(defaultType)) {
|
||||
v.newField(myClass, Opcodes.ACC_PROTECTED, "$typeInfo", "Ljet/TypeInfo;", null, null);
|
||||
|
||||
MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/TypeInfo;", null, null);
|
||||
MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD, "()Ljet/TypeInfo;", null, null);
|
||||
if (v.generateCode()) {
|
||||
mv.visitCode();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
@@ -846,7 +848,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
iv.getfield(owner, "$typeInfo", "Ljet/TypeInfo;");
|
||||
iv.areturn(JetTypeMapper.TYPE_TYPEINFO);
|
||||
FunctionCodegen.endVisit(iv, "getTypeInfo", myClass);
|
||||
FunctionCodegen.endVisit(iv, JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD, myClass);
|
||||
}
|
||||
|
||||
mv = v.newMethod(myClass, Opcodes.ACC_PROTECTED | Opcodes.ACC_FINAL, "$setTypeInfo", "(Ljet/TypeInfo;)V", null, null);
|
||||
@@ -869,14 +871,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void genGetStaticGetTypeInfoMethod() {
|
||||
final MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/TypeInfo;", null, null);
|
||||
final MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD, "()Ljet/TypeInfo;", null, null);
|
||||
if (v.generateCode()) {
|
||||
mv.visitCode();
|
||||
InstructionAdapter v = new InstructionAdapter(mv);
|
||||
String owner = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
|
||||
v.getstatic(owner, "$staticTypeInfo", "Ljet/TypeInfo;");
|
||||
v.areturn(JetTypeMapper.TYPE_TYPEINFO);
|
||||
FunctionCodegen.endVisit(v, "getTypeInfo", myClass);
|
||||
FunctionCodegen.endVisit(v, JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD, myClass);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -887,7 +889,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
public void generate(InstructionAdapter v) {
|
||||
v.aconst(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION));
|
||||
v.iconst(0);
|
||||
v.invokestatic("jet/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/TypeInfo;");
|
||||
v.invokestatic("jet/TypeInfo", JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD, "(Ljava/lang/Class;Z)Ljet/TypeInfo;");
|
||||
v.putstatic(typeMapper.mapType(descriptor.getDefaultType(), kind).getInternalName(), "$staticTypeInfo", "Ljet/TypeInfo;");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||
@@ -181,10 +182,10 @@ public class NamespaceCodegen {
|
||||
ExpressionCodegen.genTypeInfoToProjection(v, argument.getProjectionKind());
|
||||
v.astore(JetTypeMapper.TYPE_OBJECT);
|
||||
}
|
||||
v.invokestatic("jet/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/TypeInfo;");
|
||||
v.invokestatic("jet/TypeInfo", JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD, "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/TypeInfo;");
|
||||
}
|
||||
else {
|
||||
v.invokestatic("jet/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/TypeInfo;");
|
||||
v.invokestatic("jet/TypeInfo", JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD, "(Ljava/lang/Class;Z)Ljet/TypeInfo;");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
@@ -140,6 +141,7 @@ public class PropertyCodegen {
|
||||
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind).getAsmMethod().getDescriptor();
|
||||
String getterName = getterName(propertyDescriptor.getName());
|
||||
MethodVisitor mv = v.newMethod(origin, flags, getterName, signature, null, null);
|
||||
mv.visitAnnotation(JvmStdlibNames.JET_PROPERTY.getDescriptor(), true).visitEnd();
|
||||
if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
|
||||
mv.visitCode();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
@@ -184,6 +186,7 @@ public class PropertyCodegen {
|
||||
|
||||
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind).getAsmMethod().getDescriptor();
|
||||
MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), signature, null, null);
|
||||
mv.visitAnnotation(JvmStdlibNames.JET_PROPERTY.getDescriptor(), true).visitEnd();
|
||||
if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
|
||||
mv.visitCode();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
|
||||
@@ -5,6 +5,8 @@ import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
@@ -17,7 +19,7 @@ public class ValueTypeInfo implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
codegen.gen(arguments.get(0), JetTypeMapper.TYPE_JET_OBJECT);
|
||||
v.invokeinterface(JetTypeMapper.TYPE_JET_OBJECT.getInternalName(), "getTypeInfo", "()Ljet/TypeInfo;");
|
||||
v.invokeinterface(JetTypeMapper.TYPE_JET_OBJECT.getInternalName(), JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD, "()Ljet/TypeInfo;");
|
||||
return StackValue.onStack(JetTypeMapper.TYPE_TYPEINFO);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-12
@@ -21,7 +21,7 @@ public class JavaClassMembersScope implements JetScope {
|
||||
private final boolean staticMembers;
|
||||
private final DeclarationDescriptor containingDeclaration;
|
||||
private final Map<String, Set<FunctionDescriptor>> functionGroups = Maps.newHashMap();
|
||||
private final Map<String, VariableDescriptor> variables = Maps.newHashMap();
|
||||
private final Map<String, Set<VariableDescriptor>> variables = Maps.newHashMap();
|
||||
private final Map<String, ClassifierDescriptor> classifiers = Maps.newHashMap();
|
||||
private Collection<DeclarationDescriptor> allDescriptors;
|
||||
|
||||
@@ -77,13 +77,7 @@ public class JavaClassMembersScope implements JetScope {
|
||||
}
|
||||
}
|
||||
|
||||
for (PsiField field : psiClass.getAllFields()) {
|
||||
if (field.hasModifierProperty(PsiModifier.STATIC) != staticMembers) {
|
||||
continue;
|
||||
}
|
||||
VariableDescriptor variableDescriptor = semanticServices.getDescriptorResolver().resolveFieldToVariableDescriptor(containingDeclaration, field);
|
||||
allDescriptors.add(variableDescriptor);
|
||||
}
|
||||
allDescriptors.addAll(semanticServices.getDescriptorResolver().resolveFieldGroup(containingDeclaration, psiClass, staticMembers));
|
||||
}
|
||||
return allDescriptors;
|
||||
}
|
||||
@@ -116,14 +110,14 @@ public class JavaClassMembersScope implements JetScope {
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<VariableDescriptor> getProperties(@NotNull String name) {
|
||||
VariableDescriptor variableDescriptor = variables.get(name);
|
||||
Set<VariableDescriptor> variableDescriptor = variables.get(name);
|
||||
if (variableDescriptor == null) {
|
||||
variableDescriptor = doGetVariable(name);
|
||||
if (variableDescriptor != null) {
|
||||
variables.put(name, variableDescriptor);
|
||||
}
|
||||
}
|
||||
return variableDescriptor != null ? Collections.singleton(variableDescriptor) : Collections.<VariableDescriptor>emptySet();
|
||||
return variableDescriptor != null ? variableDescriptor : Collections.<VariableDescriptor>emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,14 +126,15 @@ public class JavaClassMembersScope implements JetScope {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private VariableDescriptor doGetVariable(String name) {
|
||||
private Set<VariableDescriptor> doGetVariable(String name) {
|
||||
PsiField field = psiClass.findFieldByName(name, true);
|
||||
if (field == null) return null;
|
||||
if (field.hasModifierProperty(PsiModifier.STATIC) != staticMembers) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return semanticServices.getDescriptorResolver().resolveFieldToVariableDescriptor(containingDeclaration, field);
|
||||
//return semanticServices.getDescriptorResolver().resolveFieldToVariableDescriptor(containingDeclaration, field);
|
||||
return semanticServices.getDescriptorResolver().resolveFieldGroupByName(containingDeclaration, psiClass, name, staticMembers);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+208
-4
@@ -4,6 +4,7 @@ import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.DelegatingGlobalSearchScope;
|
||||
@@ -85,8 +86,14 @@ public class JavaDescriptorResolver {
|
||||
this.lowerBoundsForKotlin = lowerBoundsForKotlin;
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class ResolverScopeData {
|
||||
@Nullable
|
||||
private Set<VariableDescriptor> properties;
|
||||
private boolean kotlin;
|
||||
}
|
||||
|
||||
private static class ResolverClassData {
|
||||
private static class ResolverClassData extends ResolverScopeData {
|
||||
private JavaClassDescriptor classDescriptor;
|
||||
private boolean kotlin;
|
||||
|
||||
@@ -96,7 +103,7 @@ public class JavaDescriptorResolver {
|
||||
}
|
||||
}
|
||||
|
||||
private static class ResolverNamespaceData {
|
||||
private static class ResolverNamespaceData extends ResolverScopeData {
|
||||
private JavaNamespaceDescriptor namespaceDescriptor;
|
||||
private boolean kotlin;
|
||||
|
||||
@@ -751,6 +758,7 @@ public class JavaDescriptorResolver {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public VariableDescriptor resolveFieldToVariableDescriptor(DeclarationDescriptor containingDeclaration, PsiField field) {
|
||||
VariableDescriptor variableDescriptor = fieldDescriptorCache.get(field);
|
||||
if (variableDescriptor != null) {
|
||||
@@ -772,6 +780,200 @@ public class JavaDescriptorResolver {
|
||||
fieldDescriptorCache.put(field, propertyDescriptor);
|
||||
return propertyDescriptor;
|
||||
}
|
||||
*/
|
||||
|
||||
private static class PropertyKey {
|
||||
@NotNull
|
||||
private final String name;
|
||||
@NotNull
|
||||
private final PsiType type;
|
||||
|
||||
private PropertyKey(String name, PsiType type) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
// generated by Idea
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
PropertyKey that = (PropertyKey) o;
|
||||
|
||||
if (!name.equals(that.name)) return false;
|
||||
if (!type.equals(that.type)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = name.hashCode();
|
||||
result = 31 * result + type.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MembersForProperty {
|
||||
private PsiField field;
|
||||
private PsiMethod setter;
|
||||
private PsiMethod getter;
|
||||
}
|
||||
|
||||
private Map<PropertyKey, MembersForProperty> getMembersForProperties(@NotNull PsiClass clazz, boolean staticMembers, boolean kotlin) {
|
||||
Map<PropertyKey, MembersForProperty> membersMap = Maps.newHashMap();
|
||||
if (!kotlin) {
|
||||
for (PsiField field : clazz.getFields()) {
|
||||
if (field.getModifierList().hasExplicitModifier(PsiModifier.STATIC) != staticMembers) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (field.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MembersForProperty members = new MembersForProperty();
|
||||
members.field = field;
|
||||
membersMap.put(new PropertyKey(field.getName(), field.getType()), members);
|
||||
}
|
||||
}
|
||||
|
||||
for (PsiMethod method : clazz.getMethods()) {
|
||||
if (method.getModifierList().hasExplicitModifier(PsiModifier.STATIC) != staticMembers) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: "is" prefix
|
||||
if (method.getName().startsWith(JvmAbi.GETTER_PREFIX)) {
|
||||
// TODO: some java properties too
|
||||
if (method.getModifierList().findAnnotation(JvmStdlibNames.JET_PROPERTY.getFqName()) != null) {
|
||||
if (method.getParameterList().getParametersCount() == 0) {
|
||||
if (method.getName().equals(JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String propertyName = StringUtil.decapitalize(method.getName().substring(JvmAbi.GETTER_PREFIX.length()));
|
||||
PropertyKey key = new PropertyKey(propertyName, method.getReturnType());
|
||||
MembersForProperty members = membersMap.get(key);
|
||||
if (members == null) {
|
||||
members = new MembersForProperty();
|
||||
membersMap.put(key, members);
|
||||
}
|
||||
members.getter = method;
|
||||
}
|
||||
}
|
||||
} else if (method.getName().startsWith(JvmAbi.SETTER_PREFIX)) {
|
||||
if (method.getModifierList().findAnnotation(JvmStdlibNames.JET_PROPERTY.getFqName()) != null) {
|
||||
if (method.getParameterList().getParametersCount() == 1) {
|
||||
String propertyName = StringUtil.decapitalize(method.getName().substring(JvmAbi.SETTER_PREFIX.length()));
|
||||
PropertyKey key = new PropertyKey(propertyName, method.getParameterList().getParameters()[0].getType());
|
||||
MembersForProperty members = membersMap.get(key);
|
||||
if (members == null) {
|
||||
members = new MembersForProperty();
|
||||
membersMap.put(key, members);
|
||||
}
|
||||
members.setter = method;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return membersMap;
|
||||
}
|
||||
|
||||
public Set<VariableDescriptor> resolveFieldGroupByName(@NotNull DeclarationDescriptor owner, PsiClass psiClass, String fieldName, boolean staticMembers) {
|
||||
Set<VariableDescriptor> r = Sets.newHashSet();
|
||||
// TODO: slow
|
||||
Set<VariableDescriptor> variables = resolveFieldGroup(owner, psiClass, staticMembers);
|
||||
for (VariableDescriptor variable : variables) {
|
||||
if (variable.getName().equals(fieldName)) {
|
||||
r.add(variable);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<VariableDescriptor> resolveFieldGroup(@NotNull DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers) {
|
||||
|
||||
ResolverScopeData scopeData;
|
||||
if (owner instanceof JavaNamespaceDescriptor) {
|
||||
scopeData = namespaceDescriptorCacheByFqn.get(((JavaNamespaceDescriptor) owner).getQualifiedName());
|
||||
} else if (owner instanceof JavaClassDescriptor) {
|
||||
scopeData = classDescriptorCache.get(psiClass.getQualifiedName());
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (scopeData == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
if (scopeData.properties != null) {
|
||||
return scopeData.properties;
|
||||
}
|
||||
|
||||
Set<VariableDescriptor> descriptors = Sets.newHashSet();
|
||||
for (Map.Entry<PropertyKey, MembersForProperty> entry : getMembersForProperties(psiClass, staticMembers, scopeData.kotlin).entrySet()) {
|
||||
//VariableDescriptor variableDescriptor = fieldDescriptorCache.get(field);
|
||||
//if (variableDescriptor != null) {
|
||||
// return variableDescriptor;
|
||||
//}
|
||||
String propertyName = entry.getKey().name;
|
||||
PsiType propertyType = entry.getKey().type;
|
||||
MembersForProperty members = entry.getValue();
|
||||
|
||||
JetType type = semanticServices.getTypeTransformer().transformToType(propertyType);
|
||||
boolean isFinal;
|
||||
if (members.setter == null && members.getter == null) {
|
||||
isFinal = members.field.hasModifierProperty(PsiModifier.FINAL);
|
||||
} else if (members.getter != null) {
|
||||
isFinal = members.getter.hasModifierProperty(PsiModifier.FINAL);
|
||||
} else if (members.setter != null) {
|
||||
isFinal = members.setter.hasModifierProperty(PsiModifier.FINAL);
|
||||
} else {
|
||||
isFinal = false;
|
||||
}
|
||||
|
||||
PsiMember anyMember;
|
||||
if (members.getter != null) {
|
||||
anyMember = members.getter;
|
||||
} else if (members.field != null) {
|
||||
anyMember = members.field;
|
||||
} else if (members.setter != null) {
|
||||
anyMember = members.setter;
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
boolean isVar;
|
||||
if (members.getter == null && members.setter == null) {
|
||||
isVar = true;
|
||||
} else {
|
||||
isVar = members.setter != null;
|
||||
}
|
||||
|
||||
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
|
||||
owner,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
isFinal && !staticMembers ? Modality.FINAL : Modality.OPEN, // TODO: abstract
|
||||
resolveVisibilityFromPsiModifiers(anyMember),
|
||||
isVar,
|
||||
null,
|
||||
DescriptorUtils.getExpectedThisObjectIfNeeded(owner),
|
||||
propertyName,
|
||||
type);
|
||||
semanticServices.getTrace().record(BindingContext.VARIABLE, anyMember, propertyDescriptor);
|
||||
//fieldDescriptorCache.put(field, propertyDescriptor);
|
||||
descriptors.add(propertyDescriptor);
|
||||
}
|
||||
scopeData.properties = descriptors;
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<FunctionDescriptor> resolveFunctionGroup(@NotNull DeclarationDescriptor owner, @NotNull PsiClass psiClass, @Nullable ClassDescriptor classDescriptor, @NotNull String methodName, boolean staticMembers) {
|
||||
@@ -870,10 +1072,12 @@ public class JavaDescriptorResolver {
|
||||
// TODO: hide getters and setters properly
|
||||
if (kotlin) {
|
||||
if (method.getName().startsWith(JvmAbi.GETTER_PREFIX) && method.getParameterList().getParametersCount() == 0) {
|
||||
return null;
|
||||
if (method.getModifierList().findAnnotation(JvmStdlibNames.JET_PROPERTY.getFqName()) != null)
|
||||
return null;
|
||||
}
|
||||
if (method.getName().startsWith(JvmAbi.SETTER_PREFIX) && method.getParameterList().getParametersCount() == 1) {
|
||||
return null;
|
||||
if (method.getModifierList().findAnnotation(JvmStdlibNames.JET_PROPERTY.getFqName()) != null)
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@ public class JavaPackageScope extends JetScopeImpl {
|
||||
}
|
||||
|
||||
// TODO: cache
|
||||
return Collections.singleton(semanticServices.getDescriptorResolver().resolveFieldToVariableDescriptor(containingDescriptor, field));
|
||||
return semanticServices.getDescriptorResolver().resolveFieldGroupByName(containingDescriptor, psiClassForPackage, name, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -26,6 +26,8 @@ public class JvmStdlibNames {
|
||||
public static final String JET_METHOD_NULLABLE_RETURN_TYPE_FIELD = "nullableReturnType";
|
||||
public static final String JET_METHOD_RETURN_TYPE_FIELD = "returnType";
|
||||
public static final String JET_METHOD_TYPE_PARAMETERS_FIELD = "typeParameters";
|
||||
|
||||
public static final JvmClassName JET_PROPERTY = new JvmClassName("jet.typeinfo.JetProperty");
|
||||
|
||||
|
||||
public static final JvmClassName JET_CLASS = new JvmClassName("jet.typeinfo.JetClass");
|
||||
@@ -34,6 +36,8 @@ public class JvmStdlibNames {
|
||||
|
||||
|
||||
public static final JvmClassName JET_OBJECT = new JvmClassName("jet.JetObject");
|
||||
|
||||
public static final String JET_OBJECT_GET_TYPEINFO_METHOD = "getTypeInfo";
|
||||
|
||||
|
||||
private JvmStdlibNames() {
|
||||
|
||||
+3
-1
@@ -118,7 +118,9 @@ public class DataFlowValueFactory {
|
||||
if (classDescriptor.getModality().isOverridable() && propertyDescriptor.getModality().isOverridable()) return false;
|
||||
}
|
||||
else {
|
||||
assert !propertyDescriptor.getModality().isOverridable() : "Property outside a class must not be overridable";
|
||||
if (propertyDescriptor.getModality().isOverridable()) {
|
||||
throw new IllegalStateException("Property outside a class must not be overridable: " + propertyDescriptor.getName());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package test
|
||||
|
||||
class ClassFunGetFoo {
|
||||
fun getFoo() = 1
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
class ClassFunGetFoo {
|
||||
fun getFoo() = 1
|
||||
fun setFoo(p: Int) {}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package test
|
||||
|
||||
class ClassFunGetFoo {
|
||||
fun set(p: Int) { }
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package test
|
||||
|
||||
fun getFoo() = 1
|
||||
@@ -0,0 +1,5 @@
|
||||
package test
|
||||
|
||||
abstract class ClassValAbstract {
|
||||
abstract val a: Int
|
||||
}
|
||||
@@ -125,6 +125,7 @@ public class ReadClassDataTest extends UsefulTestCase {
|
||||
for (DeclarationDescriptor ad : nsa.getMemberScope().getAllDescriptors()) {
|
||||
if (ad instanceof ClassifierDescriptor) {
|
||||
ClassifierDescriptor bd = nsb.getMemberScope().getClassifier(ad.getName());
|
||||
Assert.assertTrue("classifier not found: " + ad.getName(), bd != null);
|
||||
compareClassifiers((ClassifierDescriptor) ad, bd);
|
||||
|
||||
Assert.assertNull(nsb.getMemberScope().getClassifier(ad.getName() + JvmAbi.TRAIT_IMPL_SUFFIX));
|
||||
@@ -136,7 +137,7 @@ public class ReadClassDataTest extends UsefulTestCase {
|
||||
compareDescriptors(ad, bd);
|
||||
} else if (ad instanceof PropertyDescriptor) {
|
||||
Set<VariableDescriptor> properties = nsb.getMemberScope().getProperties(ad.getName());
|
||||
Assert.assertTrue(properties.size() >= 1);
|
||||
Assert.assertTrue("property not found by name: " + ad.getName(), properties.size() >= 1);
|
||||
Assert.assertTrue("not implemented", properties.size() == 1);
|
||||
PropertyDescriptor bd = (PropertyDescriptor) properties.iterator().next();
|
||||
compareDescriptors(ad, bd);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package jet.typeinfo;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface JetProperty {
|
||||
}
|
||||
Reference in New Issue
Block a user