001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.lang.resolve.java.resolver;
018
019 import com.intellij.openapi.application.ApplicationManager;
020 import com.intellij.openapi.diagnostic.Logger;
021 import com.intellij.psi.PsiExpression;
022 import com.intellij.psi.PsiField;
023 import com.intellij.psi.PsiLiteralExpression;
024 import org.jetbrains.annotations.NotNull;
025 import org.jetbrains.annotations.Nullable;
026 import org.jetbrains.jet.lang.descriptors.*;
027 import org.jetbrains.jet.lang.resolve.AnnotationUtils;
028 import org.jetbrains.jet.lang.resolve.BindingContextUtils;
029 import org.jetbrains.jet.lang.resolve.BindingTrace;
030 import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
031 import org.jetbrains.jet.lang.resolve.java.JavaBindingContext;
032 import org.jetbrains.jet.lang.resolve.java.JavaNamespaceKind;
033 import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
034 import org.jetbrains.jet.lang.resolve.java.structure.JavaElement;
035 import org.jetbrains.jet.lang.resolve.java.structure.JavaField;
036 import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
037 import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaClassImpl;
038 import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaElementImpl;
039 import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaFieldImpl;
040 import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaMethodImpl;
041 import org.jetbrains.jet.lang.resolve.name.FqName;
042 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
043 import org.jetbrains.jet.rt.annotation.AssertInvisibleInResolver;
044
045 import javax.inject.Inject;
046
047 import static org.jetbrains.jet.lang.resolve.BindingContext.*;
048 import static org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils.fqNameByClass;
049
050 public class TraceBasedJavaResolverCache implements JavaResolverCache {
051 private static final Logger LOG = Logger.getInstance(TraceBasedJavaResolverCache.class);
052 private static final FqName ASSERT_INVISIBLE_IN_RESOLVER_ANNOTATION = fqNameByClass(AssertInvisibleInResolver.class);
053
054 private BindingTrace trace;
055
056 @Inject
057 public void setTrace(BindingTrace trace) {
058 this.trace = trace;
059 }
060
061 @Nullable
062 @Override
063 public ClassDescriptor getClassResolvedFromSource(@NotNull FqName fqName) {
064 return trace.get(FQNAME_TO_CLASS_DESCRIPTOR, fqName);
065 }
066
067 @Nullable
068 @Override
069 public NamespaceDescriptor getPackageResolvedFromSource(@NotNull FqName fqName) {
070 return trace.get(FQNAME_TO_NAMESPACE_DESCRIPTOR, fqName);
071 }
072
073 @Nullable
074 @Override
075 public SimpleFunctionDescriptor getMethod(@NotNull JavaMethod method) {
076 return trace.get(FUNCTION, ((JavaMethodImpl) method).getPsi());
077 }
078
079 @Nullable
080 @Override
081 public ConstructorDescriptor getConstructor(@NotNull JavaElement constructor) {
082 return trace.get(CONSTRUCTOR, ((JavaElementImpl) constructor).getPsi());
083 }
084
085 @Nullable
086 @Override
087 public ClassDescriptor getClass(@NotNull JavaClass javaClass) {
088 FqName fqName = javaClass.getFqName();
089 if (fqName != null && KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME.equals(fqName.parent())) {
090 if (javaClass.findAnnotation(ASSERT_INVISIBLE_IN_RESOLVER_ANNOTATION) != null) {
091 if (ApplicationManager.getApplication().isInternal()) {
092 LOG.error("Classpath is configured incorrectly:" +
093 " class " + fqName + " from runtime must not be loaded by compiler");
094 }
095 return null;
096 }
097 }
098
099 return trace.get(CLASS, ((JavaClassImpl) javaClass).getPsi());
100 }
101
102 @Override
103 public void recordMethod(@NotNull JavaMethod method, @NotNull SimpleFunctionDescriptor descriptor) {
104 BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, ((JavaMethodImpl) method).getPsi(), descriptor);
105 }
106
107 @Override
108 public void recordConstructor(@NotNull JavaElement element, @NotNull ConstructorDescriptor descriptor) {
109 trace.record(CONSTRUCTOR, ((JavaElementImpl) element).getPsi(), descriptor);
110 }
111
112 @Override
113 public void recordField(@NotNull JavaField field, @NotNull PropertyDescriptor descriptor) {
114 PsiField psiField = ((JavaFieldImpl) field).getPsi();
115 trace.record(VARIABLE, psiField, descriptor);
116
117 if (AnnotationUtils.isPropertyAcceptableAsAnnotationParameter(descriptor)) {
118 PsiExpression initializer = psiField.getInitializer();
119 if (initializer instanceof PsiLiteralExpression) {
120 CompileTimeConstant<?> constant = JavaAnnotationArgumentResolver
121 .resolveCompileTimeConstantValue(((PsiLiteralExpression) initializer).getValue(), descriptor.getType());
122 if (constant != null) {
123 trace.record(COMPILE_TIME_INITIALIZER, descriptor, constant);
124 }
125 }
126 }
127 }
128
129 @Override
130 public void recordClass(@NotNull JavaClass javaClass, @NotNull ClassDescriptor descriptor) {
131 trace.record(CLASS, ((JavaClassImpl) javaClass).getPsi(), descriptor);
132 }
133
134 @Override
135 public void recordProperNamespace(@NotNull NamespaceDescriptor descriptor) {
136 trace.record(JavaBindingContext.JAVA_NAMESPACE_KIND, descriptor, JavaNamespaceKind.PROPER);
137 }
138
139 @Override
140 public void recordClassStaticMembersNamespace(@NotNull NamespaceDescriptor descriptor) {
141 trace.record(JavaBindingContext.JAVA_NAMESPACE_KIND, descriptor, JavaNamespaceKind.CLASS_STATICS);
142 }
143
144 @Override
145 public void recordPackage(@NotNull JavaElement element, @NotNull NamespaceDescriptor descriptor) {
146 trace.record(NAMESPACE, ((JavaElementImpl) element).getPsi(), descriptor);
147 }
148 }