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 017package org.jetbrains.jet.lang.resolve; 018 019import com.google.common.base.Function; 020import com.google.common.base.Functions; 021import com.google.common.collect.Maps; 022import com.intellij.psi.PsiElement; 023import com.intellij.psi.PsiFile; 024import org.jetbrains.annotations.NotNull; 025import org.jetbrains.jet.lang.descriptors.*; 026import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; 027import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptorLite; 028import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorImpl; 029import org.jetbrains.jet.lang.psi.*; 030import org.jetbrains.jet.lang.resolve.scopes.JetScope; 031import org.jetbrains.jet.lang.resolve.scopes.WritableScope; 032 033import javax.inject.Inject; 034import java.io.PrintStream; 035import java.util.Collection; 036import java.util.List; 037import java.util.Map; 038 039public class TopDownAnalysisContext implements BodiesResolveContext { 040 041 private final Map<JetClass, MutableClassDescriptor> classes = Maps.newLinkedHashMap(); 042 private final Map<JetObjectDeclaration, MutableClassDescriptor> objects = Maps.newLinkedHashMap(); 043 protected final Map<JetFile, NamespaceDescriptorImpl> namespaceDescriptors = Maps.newHashMap(); 044 private List<MutableClassDescriptorLite> classesTopologicalOrder = null; 045 046 private final Map<JetDeclaration, JetScope> declaringScopes = Maps.newHashMap(); 047 private final Map<JetNamedFunction, SimpleFunctionDescriptor> functions = Maps.newLinkedHashMap(); 048 private final Map<JetProperty, PropertyDescriptor> properties = Maps.newLinkedHashMap(); 049 private final Map<JetParameter, PropertyDescriptor> primaryConstructorParameterProperties = Maps.newHashMap(); 050 private Map<JetDeclaration, CallableMemberDescriptor> members = null; 051 052 // File scopes - package scope extended with imports 053 protected final Map<JetFile, WritableScope> namespaceScopes = Maps.newHashMap(); 054 055 public final Map<JetDeclarationContainer, DeclarationDescriptor> forDeferredResolver = Maps.newHashMap(); 056 057 public final Map<JetDeclarationContainer, JetScope> normalScope = Maps.newHashMap(); 058 059 private final Map<JetScript, ScriptDescriptor> scripts = Maps.newLinkedHashMap(); 060 private final Map<JetScript, WritableScope> scriptScopes = Maps.newHashMap(); 061 062 private StringBuilder debugOutput; 063 064 065 private TopDownAnalysisParameters topDownAnalysisParameters; 066 067 @Override 068 @Inject 069 public void setTopDownAnalysisParameters(TopDownAnalysisParameters topDownAnalysisParameters) { 070 this.topDownAnalysisParameters = topDownAnalysisParameters; 071 } 072 073 public TopDownAnalysisParameters getTopDownAnalysisParameters() { 074 return topDownAnalysisParameters; 075 } 076 077 public void debug(Object message) { 078 if (debugOutput != null) { 079 debugOutput.append(message).append("\n"); 080 } 081 } 082 083 @SuppressWarnings("UnusedDeclaration") 084 /*package*/ void enableDebugOutput() { 085 if (debugOutput == null) { 086 debugOutput = new StringBuilder(); 087 } 088 } 089 090 /*package*/ void printDebugOutput(PrintStream out) { 091 if (debugOutput != null) { 092 out.print(debugOutput); 093 } 094 } 095 096 @Override 097 public boolean completeAnalysisNeeded(@NotNull PsiElement element) { 098 PsiFile containingFile = element.getContainingFile(); 099 boolean result = containingFile != null && topDownAnalysisParameters.getAnalyzeCompletely().apply(containingFile); 100 if (!result) { 101 debug(containingFile); 102 } 103 return result; 104 } 105 106 @Override 107 public Map<JetClass, MutableClassDescriptor> getClasses() { 108 return classes; 109 } 110 111 @Override 112 public Map<JetObjectDeclaration, MutableClassDescriptor> getObjects() { 113 return objects; 114 } 115 116 public Map<JetFile, WritableScope> getNamespaceScopes() { 117 return namespaceScopes; 118 } 119 120 public Map<JetFile, NamespaceDescriptorImpl> getNamespaceDescriptors() { 121 return namespaceDescriptors; 122 } 123 124 @Override 125 public Collection<JetFile> getFiles() { 126 return namespaceDescriptors.keySet(); 127 } 128 129 @Override 130 @NotNull 131 public Map<JetScript, ScriptDescriptor> getScripts() { 132 return scripts; 133 } 134 135 @Override 136 @NotNull 137 public Map<JetScript, WritableScope> getScriptScopes() { 138 return scriptScopes; 139 } 140 141 public Map<JetParameter, PropertyDescriptor> getPrimaryConstructorParameterProperties() { 142 return primaryConstructorParameterProperties; 143 } 144 145 @Override 146 public Map<JetProperty, PropertyDescriptor> getProperties() { 147 return properties; 148 } 149 150 @Override 151 public Function<JetDeclaration, JetScope> getDeclaringScopes() { 152 return Functions.forMap(declaringScopes); 153 } 154 155 public void registerDeclaringScope(@NotNull JetDeclaration declaration, @NotNull JetScope scope) { 156 declaringScopes.put(declaration, scope); 157 } 158 159 @Override 160 public Map<JetNamedFunction, SimpleFunctionDescriptor> getFunctions() { 161 return functions; 162 } 163 164 public Map<JetDeclaration, CallableMemberDescriptor> getMembers() { 165 if (members == null) { 166 members = Maps.newHashMap(); 167 members.putAll(functions); 168 members.putAll(properties); 169 members.putAll(primaryConstructorParameterProperties); 170 } 171 return members; 172 } 173 174 @NotNull 175 public List<MutableClassDescriptorLite> getClassesTopologicalOrder() { 176 return classesTopologicalOrder; 177 } 178 179 public void setClassesTopologicalOrder(@NotNull List<MutableClassDescriptorLite> classesTopologicalOrder) { 180 this.classesTopologicalOrder = classesTopologicalOrder; 181 } 182}