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    }