提交 1bb58286 编写于 作者: S Stepan Koltsov

reading properties info from binary classes

Add final modifier to val backing field
上级 047fe9df
......@@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
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.lexer.JetTokens;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
......@@ -65,7 +66,7 @@ public class PropertyCodegen {
value = compileTimeValue != null ? compileTimeValue.getValue() : null;
}
}
final int modifiers;
int modifiers;
if (kind == OwnerKind.NAMESPACE) {
int access = isExternallyAccessible(p) ? Opcodes.ACC_PUBLIC : Opcodes.ACC_PRIVATE;
modifiers = access | Opcodes.ACC_STATIC;
......@@ -73,6 +74,9 @@ public class PropertyCodegen {
else {
modifiers = Opcodes.ACC_PRIVATE;
}
if (!propertyDescriptor.isVar()) {
modifiers |= Opcodes.ACC_FINAL;
}
v.newField(p, modifiers, p.getName(), state.getTypeMapper().mapType(propertyDescriptor.getOutType()).getDescriptor(), null, value);
}
}
......@@ -212,10 +216,10 @@ public class PropertyCodegen {
}
public static String getterName(String propertyName) {
return "get" + StringUtil.capitalizeWithJavaBeanConvention(propertyName);
return JvmAbi.GETTER_PREFIX + StringUtil.capitalizeWithJavaBeanConvention(propertyName);
}
public static String setterName(String propertyName) {
return "set" + StringUtil.capitalizeWithJavaBeanConvention(propertyName);
return JvmAbi.SETTER_PREFIX + StringUtil.capitalizeWithJavaBeanConvention(propertyName);
}
}
......@@ -96,11 +96,23 @@ public class JavaDescriptorResolver {
}
}
private static class ResolverNamespaceData {
private JavaNamespaceDescriptor namespaceDescriptor;
private boolean kotlin;
@NotNull
public NamespaceDescriptor getNamespaceDescriptor() {
return namespaceDescriptor;
}
}
protected final Map<String, ResolverClassData> classDescriptorCache = Maps.newHashMap();
protected final Map<String, ResolverNamespaceData> namespaceDescriptorCacheByFqn = Maps.newHashMap();
protected final Map<PsiElement, ResolverNamespaceData> namespaceDescriptorCache = Maps.newHashMap();
protected final Map<PsiTypeParameter, TypeParameterDescriptorInitialization> typeParameterDescriptorCache = Maps.newHashMap();
protected final Map<PsiMethod, FunctionDescriptor> methodDescriptorCache = Maps.newHashMap();
protected final Map<PsiField, VariableDescriptor> fieldDescriptorCache = Maps.newHashMap();
protected final Map<PsiElement, NamespaceDescriptor> namespaceDescriptorCache = Maps.newHashMap();
protected final JavaPsiFacade javaFacade;
protected final GlobalSearchScope javaSearchScope;
protected final JavaSemanticServices semanticServices;
......@@ -535,34 +547,40 @@ public class JavaDescriptorResolver {
}
private NamespaceDescriptor resolveNamespace(@NotNull PsiPackage psiPackage) {
NamespaceDescriptor namespaceDescriptor = namespaceDescriptorCache.get(psiPackage);
if (namespaceDescriptor == null) {
namespaceDescriptor = createJavaNamespaceDescriptor(psiPackage);
namespaceDescriptorCache.put(psiPackage, namespaceDescriptor);
ResolverNamespaceData namespaceData = namespaceDescriptorCache.get(psiPackage);
if (namespaceData == null) {
namespaceData = createJavaNamespaceDescriptor(psiPackage);
namespaceDescriptorCache.put(psiPackage, namespaceData);
namespaceDescriptorCacheByFqn.put(psiPackage.getQualifiedName(), namespaceData);
}
return namespaceDescriptor;
return namespaceData.namespaceDescriptor;
}
private NamespaceDescriptor resolveNamespace(@NotNull PsiClass psiClass) {
NamespaceDescriptor namespaceDescriptor = namespaceDescriptorCache.get(psiClass);
if (namespaceDescriptor == null) {
namespaceDescriptor = createJavaNamespaceDescriptor(psiClass);
namespaceDescriptorCache.put(psiClass, namespaceDescriptor);
ResolverNamespaceData namespaceData = namespaceDescriptorCache.get(psiClass);
if (namespaceData == null) {
namespaceData = createJavaNamespaceDescriptor(psiClass);
namespaceDescriptorCache.put(psiClass, namespaceData);
namespaceDescriptorCacheByFqn.put(psiClass.getQualifiedName(), namespaceData);
}
return namespaceDescriptor;
return namespaceData.namespaceDescriptor;
}
private NamespaceDescriptor createJavaNamespaceDescriptor(@NotNull PsiPackage psiPackage) {
private ResolverNamespaceData createJavaNamespaceDescriptor(@NotNull PsiPackage psiPackage) {
ResolverNamespaceData namespaceData = new ResolverNamespaceData();
String name = psiPackage.getName();
JavaNamespaceDescriptor namespaceDescriptor = new JavaNamespaceDescriptor(
namespaceData.namespaceDescriptor = new JavaNamespaceDescriptor(
resolveParentDescriptor(psiPackage),
Collections.<AnnotationDescriptor>emptyList(), // TODO
name == null ? JAVA_ROOT : name
name == null ? JAVA_ROOT : name,
name == null ? JAVA_ROOT : psiPackage.getQualifiedName()
);
namespaceDescriptor.setMemberScope(new JavaPackageScope(psiPackage.getQualifiedName(), namespaceDescriptor, semanticServices));
semanticServices.getTrace().record(BindingContext.NAMESPACE, psiPackage, namespaceDescriptor);
return namespaceDescriptor;
namespaceData.namespaceDescriptor.setMemberScope(new JavaPackageScope(psiPackage.getQualifiedName(), namespaceData.namespaceDescriptor, semanticServices));
semanticServices.getTrace().record(BindingContext.NAMESPACE, psiPackage, namespaceData.namespaceDescriptor);
// TODO: hack
namespaceData.kotlin = true;
return namespaceData;
}
private DeclarationDescriptor resolveParentDescriptor(@NotNull PsiPackage psiPackage) {
......@@ -573,15 +591,17 @@ public class JavaDescriptorResolver {
return resolveNamespace(parentPackage);
}
private NamespaceDescriptor createJavaNamespaceDescriptor(@NotNull final PsiClass psiClass) {
JavaNamespaceDescriptor namespaceDescriptor = new JavaNamespaceDescriptor(
private ResolverNamespaceData createJavaNamespaceDescriptor(@NotNull final PsiClass psiClass) {
ResolverNamespaceData namespaceData = new ResolverNamespaceData();
namespaceData.namespaceDescriptor = new JavaNamespaceDescriptor(
resolveParentDescriptor(psiClass),
Collections.<AnnotationDescriptor>emptyList(), // TODO
psiClass.getName()
psiClass.getName(),
psiClass.getQualifiedName()
);
namespaceDescriptor.setMemberScope(new JavaClassMembersScope(namespaceDescriptor, psiClass, semanticServices, true));
semanticServices.getTrace().record(BindingContext.NAMESPACE, psiClass, namespaceDescriptor);
return namespaceDescriptor;
namespaceData.namespaceDescriptor.setMemberScope(new JavaClassMembersScope(namespaceData.namespaceDescriptor, psiClass, semanticServices, true));
semanticServices.getTrace().record(BindingContext.NAMESPACE, psiClass, namespaceData.namespaceDescriptor);
return namespaceData;
}
private static class ValueParameterDescriptors {
......@@ -831,6 +851,33 @@ public class JavaDescriptorResolver {
}
return functionDescriptor;
}
boolean kotlin;
if (owner instanceof JavaNamespaceDescriptor) {
JavaNamespaceDescriptor javaNamespaceDescriptor = (JavaNamespaceDescriptor) owner;
ResolverNamespaceData namespaceData = namespaceDescriptorCacheByFqn.get(javaNamespaceDescriptor.getQualifiedName());
if (namespaceData == null) {
throw new IllegalStateException("namespaceData not found by name " + javaNamespaceDescriptor.getQualifiedName());
}
kotlin = namespaceData.kotlin;
} else {
ResolverClassData classData = classDescriptorCache.get(psiClass.getQualifiedName());
if (classData == null) {
throw new IllegalStateException("classData not found by name " + psiClass.getQualifiedName());
}
kotlin = classData.kotlin;
}
// TODO: hide getters and setters properly
if (kotlin) {
if (method.getName().startsWith(JvmAbi.GETTER_PREFIX) && method.getParameterList().getParametersCount() == 0) {
return null;
}
if (method.getName().startsWith(JvmAbi.SETTER_PREFIX) && method.getParameterList().getParametersCount() == 1) {
return null;
}
}
DeclarationDescriptor classDescriptor;
final List<TypeParameterDescriptor> classTypeParameters;
if (method.hasModifierProperty(PsiModifier.STATIC)) {
......
......@@ -13,9 +13,12 @@ import java.util.List;
*/
public class JavaNamespaceDescriptor extends AbstractNamespaceDescriptorImpl {
private JetScope memberScope;
public JavaNamespaceDescriptor(DeclarationDescriptor containingDeclaration, List<AnnotationDescriptor> annotations, String name) {
private final String qualifiedName;
public JavaNamespaceDescriptor(DeclarationDescriptor containingDeclaration, List<AnnotationDescriptor> annotations,
@NotNull String name, @NotNull String qualifiedName) {
super(containingDeclaration, annotations, name);
this.qualifiedName = qualifiedName;
}
public void setMemberScope(@NotNull JetScope memberScope) {
......@@ -27,4 +30,8 @@ public class JavaNamespaceDescriptor extends AbstractNamespaceDescriptorImpl {
public JetScope getMemberScope() {
return memberScope;
}
public String getQualifiedName() {
return qualifiedName;
}
}
......@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.resolve.java;
import com.google.common.collect.Sets;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiPackage;
import org.jetbrains.annotations.NotNull;
......@@ -37,29 +38,59 @@ public class JavaPackageScope extends JetScopeImpl {
public NamespaceDescriptor getNamespace(@NotNull String name) {
return semanticServices.getDescriptorResolver().resolveNamespace(getQualifiedName(name));
}
@NotNull
@Override
public Set<FunctionDescriptor> getFunctions(@NotNull String name) {
private PsiClass getPsiClassForPackage() {
// If this package is actually a Kotlin namespace, then we access it through a namespace descriptor, and
// Kotlin functions are already there
NamespaceDescriptor kotlinNamespaceDescriptor = semanticServices.getKotlinNamespaceDescriptor(packageFQN);
if (kotlinNamespaceDescriptor != null) {
return Collections.emptySet();
return null;
}
// TODO: what is GlobalSearchScope
PsiClass psiClass = semanticServices.getDescriptorResolver().javaFacade.findClass(getQualifiedName("namespace"));
if (psiClass == null) {
return Collections.emptySet();
return null;
}
if (containingDescriptor == null) {
return null;
}
return psiClass;
}
@NotNull
@Override
public Set<FunctionDescriptor> getFunctions(@NotNull String name) {
PsiClass psiClassForPackage = getPsiClassForPackage();
if (psiClassForPackage == null) {
return Collections.emptySet();
}
return semanticServices.getDescriptorResolver().resolveFunctionGroup(containingDescriptor, psiClass, null, name, true);
// return Collections.emptySet();
return semanticServices.getDescriptorResolver().resolveFunctionGroup(containingDescriptor, psiClassForPackage, null, name, true);
}
@NotNull
@Override
public Set<VariableDescriptor> getProperties(@NotNull String name) {
PsiClass psiClassForPackage = getPsiClassForPackage();
if (psiClassForPackage == null) {
return Collections.emptySet();
}
PsiField field = psiClassForPackage.findFieldByName(name, true);
if (field == null) {
return null;
}
if (!field.hasModifierProperty(PsiModifier.STATIC)) {
return null;
}
// TODO: cache
return Collections.singleton(semanticServices.getDescriptorResolver().resolveFieldToVariableDescriptor(containingDescriptor, field));
}
@NotNull
......
......@@ -6,4 +6,6 @@ package org.jetbrains.jet.lang.resolve.java;
public class JvmAbi {
public static final String TRAIT_IMPL_SUFFIX = "$$TImpl";
public static final String DEFAULT_PARAMS_IMPL_SUFFIX = "$default";
public static final String GETTER_PREFIX = "get";
public static final String SETTER_PREFIX = "set";
}
package test
class ClassVal() {
val aa = 1
}
package test
class ClassVar() {
var aa = 1
}
......@@ -13,6 +13,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.codegen.ClassBuilderFactory;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.codegen.PropertyCodegen;
import org.jetbrains.jet.compiler.CompileEnvironment;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.*;
......@@ -132,7 +133,16 @@ public class ReadClassDataTest extends UsefulTestCase {
Assert.assertTrue(functions.size() >= 1);
Assert.assertTrue("not implemented", functions.size() == 1);
FunctionDescriptor bd = functions.iterator().next();
compareFunctions((FunctionDescriptor) ad, bd);
compareDescriptors(ad, bd);
} else if (ad instanceof PropertyDescriptor) {
Set<VariableDescriptor> properties = nsb.getMemberScope().getProperties(ad.getName());
Assert.assertTrue(properties.size() >= 1);
Assert.assertTrue("not implemented", properties.size() == 1);
PropertyDescriptor bd = (PropertyDescriptor) properties.iterator().next();
compareDescriptors(ad, bd);
Assert.assertTrue(nsb.getMemberScope().getFunctions(PropertyCodegen.getterName(ad.getName())).isEmpty());
Assert.assertTrue(nsb.getMemberScope().getFunctions(PropertyCodegen.setterName(ad.getName())).isEmpty());
} else {
throw new AssertionError("Unknown member: " + ad);
}
......@@ -153,7 +163,7 @@ public class ReadClassDataTest extends UsefulTestCase {
System.out.println(as);
}
private void compareFunctions(@NotNull FunctionDescriptor a, @NotNull FunctionDescriptor b) {
private void compareDescriptors(@NotNull DeclarationDescriptor a, @NotNull DeclarationDescriptor b) {
StringBuilder sba = new StringBuilder();
StringBuilder sbb = new StringBuilder();
new Serializer(sba).serialize(a);
......
......@@ -58,7 +58,7 @@ public class PropertyGenTest extends CodegenTestCase {
final Field field = fields[0];
field.setAccessible(true);
assertEquals("x", field.getName());
assertEquals(Modifier.PRIVATE | Modifier.STATIC, field.getModifiers());
assertEquals(Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL, field.getModifiers());
assertEquals(239, field.get(null));
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册