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.Predicates; 020import com.intellij.openapi.project.Project; 021import com.intellij.psi.PsiElement; 022import com.intellij.psi.PsiFile; 023import org.jetbrains.annotations.NotNull; 024import org.jetbrains.jet.di.InjectorForTopDownAnalyzerBasic; 025import org.jetbrains.jet.lang.ModuleConfiguration; 026import org.jetbrains.jet.lang.PlatformToKotlinClassMap; 027import org.jetbrains.jet.lang.descriptors.*; 028import org.jetbrains.jet.lang.descriptors.impl.*; 029import org.jetbrains.jet.lang.psi.JetClassOrObject; 030import org.jetbrains.jet.lang.psi.JetDeclaration; 031import org.jetbrains.jet.lang.psi.JetFile; 032import org.jetbrains.jet.lang.resolve.name.FqName; 033import org.jetbrains.jet.lang.resolve.name.Name; 034import org.jetbrains.jet.lang.resolve.scopes.JetScope; 035import org.jetbrains.jet.lang.resolve.scopes.WritableScope; 036import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; 037import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 038 039import javax.inject.Inject; 040import java.util.*; 041 042public class TopDownAnalyzer { 043 044 @NotNull 045 private DeclarationResolver declarationResolver; 046 @NotNull 047 private TypeHierarchyResolver typeHierarchyResolver; 048 @NotNull 049 private OverrideResolver overrideResolver; 050 @NotNull 051 private OverloadResolver overloadResolver; 052 @NotNull 053 private TopDownAnalysisParameters topDownAnalysisParameters; 054 @NotNull 055 private TopDownAnalysisContext context; 056 @NotNull 057 private BindingTrace trace; 058 @NotNull 059 private ModuleDescriptor moduleDescriptor; 060 @NotNull 061 private NamespaceFactoryImpl namespaceFactory; 062 @NotNull 063 private BodyResolver bodyResolver; 064 065 @Inject 066 public void setDeclarationResolver(@NotNull DeclarationResolver declarationResolver) { 067 this.declarationResolver = declarationResolver; 068 } 069 070 @Inject 071 public void setTypeHierarchyResolver(@NotNull TypeHierarchyResolver typeHierarchyResolver) { 072 this.typeHierarchyResolver = typeHierarchyResolver; 073 } 074 075 @Inject 076 public void setOverrideResolver(@NotNull OverrideResolver overrideResolver) { 077 this.overrideResolver = overrideResolver; 078 } 079 080 @Inject 081 public void setOverloadResolver(@NotNull OverloadResolver overloadResolver) { 082 this.overloadResolver = overloadResolver; 083 } 084 085 @Inject 086 public void setTopDownAnalysisParameters(@NotNull TopDownAnalysisParameters topDownAnalysisParameters) { 087 this.topDownAnalysisParameters = topDownAnalysisParameters; 088 } 089 090 @Inject 091 public void setTrace(@NotNull BindingTrace trace) { 092 this.trace = trace; 093 } 094 095 @Inject 096 public void setContext(@NotNull TopDownAnalysisContext context) { 097 this.context = context; 098 } 099 100 @Inject 101 public void setModuleDescriptor(@NotNull ModuleDescriptor moduleDescriptor) { 102 this.moduleDescriptor = moduleDescriptor; 103 } 104 105 @Inject 106 public void setNamespaceFactory(@NotNull NamespaceFactoryImpl namespaceFactory) { 107 this.namespaceFactory = namespaceFactory; 108 } 109 110 @Inject 111 public void setBodyResolver(@NotNull BodyResolver bodyResolver) { 112 this.bodyResolver = bodyResolver; 113 } 114 115 116 117 public void doProcess( 118 JetScope outerScope, 119 NamespaceLikeBuilder owner, 120 Collection<? extends PsiElement> declarations) { 121// context.enableDebugOutput(); 122 context.debug("Enter"); 123 124 typeHierarchyResolver.process(outerScope, owner, declarations); 125 declarationResolver.process(outerScope); 126 overrideResolver.process(); 127 128 lockScopes(); 129 130 overloadResolver.process(); 131 132 if (!topDownAnalysisParameters.isAnalyzingBootstrapLibrary()) { 133 bodyResolver.resolveBodies(); 134 } 135 136 context.debug("Exit"); 137 context.printDebugOutput(System.out); 138 } 139 140 private void lockScopes() { 141 for (MutableClassDescriptor mutableClassDescriptor : context.getClasses().values()) { 142 mutableClassDescriptor.lockScopes(); 143 } 144 for (MutableClassDescriptor mutableClassDescriptor : context.getObjects().values()) { 145 mutableClassDescriptor.lockScopes(); 146 } 147 for (Map.Entry<JetFile, WritableScope> namespaceScope : context.getNamespaceScopes().entrySet()) { 148 // todo: this is hack in favor of REPL 149 if(!namespaceScope.getKey().isScript()) 150 namespaceScope.getValue().changeLockLevel(WritableScope.LockLevel.READING); 151 } 152 } 153 154 public static void processStandardLibraryNamespace( 155 @NotNull Project project, 156 @NotNull BindingTrace trace, 157 @NotNull WritableScope outerScope, 158 @NotNull NamespaceDescriptorImpl standardLibraryNamespace, 159 @NotNull List<JetFile> files) { 160 161 TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters( 162 Predicates.<PsiFile>alwaysFalse(), true, false, Collections.<AnalyzerScriptParameter>emptyList()); 163 InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic( 164 project, topDownAnalysisParameters, new ObservableBindingTrace(trace), 165 KotlinBuiltIns.getInstance().getBuiltInsModule()); 166 167 injector.getTopDownAnalyzer().doProcessStandardLibraryNamespace(outerScope, standardLibraryNamespace, files); 168 } 169 170 private void doProcessStandardLibraryNamespace( 171 WritableScope outerScope, NamespaceDescriptorImpl standardLibraryNamespace, List<JetFile> files) { 172 ArrayList<JetDeclaration> toAnalyze = new ArrayList<JetDeclaration>(); 173 for(JetFile file : files) { 174 context.getNamespaceDescriptors().put(file, standardLibraryNamespace); 175 context.getNamespaceScopes().put(file, standardLibraryNamespace.getMemberScope()); 176 toAnalyze.addAll(file.getDeclarations()); 177 } 178// context.getDeclaringScopes().put(file, outerScope); 179 180 doProcess(outerScope, standardLibraryNamespace.getBuilder(), toAnalyze); 181 } 182 183 public static void processClassOrObject( 184 @NotNull Project project, 185 @NotNull BindingTrace trace, 186 @NotNull JetScope outerScope, 187 @NotNull final DeclarationDescriptor containingDeclaration, 188 @NotNull JetClassOrObject object 189 ) { 190 ModuleDescriptorImpl moduleDescriptor = new ModuleDescriptorImpl(Name.special("<dummy for object>"), 191 Collections.<ImportPath>emptyList(), 192 PlatformToKotlinClassMap.EMPTY); 193 moduleDescriptor.setModuleConfiguration(ModuleConfiguration.EMPTY); 194 195 TopDownAnalysisParameters topDownAnalysisParameters = 196 new TopDownAnalysisParameters(Predicates.equalTo(object.getContainingFile()), 197 false, true, Collections.<AnalyzerScriptParameter>emptyList()); 198 199 InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic( 200 project, topDownAnalysisParameters, new ObservableBindingTrace(trace), moduleDescriptor); 201 202 injector.getTopDownAnalyzer().doProcess(outerScope, new NamespaceLikeBuilder() { 203 204 @NotNull 205 @Override 206 public DeclarationDescriptor getOwnerForChildren() { 207 return containingDeclaration; 208 } 209 210 @Override 211 public void addClassifierDescriptor(@NotNull MutableClassDescriptorLite classDescriptor) { 212 213 } 214 215 @Override 216 public void addObjectDescriptor(@NotNull MutableClassDescriptorLite objectDescriptor) { 217 218 } 219 220 @Override 221 public void addFunctionDescriptor(@NotNull SimpleFunctionDescriptor functionDescriptor) { 222 throw new UnsupportedOperationException(); 223 } 224 225 @Override 226 public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) { 227 228 } 229 230 @Override 231 public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptorLite classObjectDescriptor) { 232 return ClassObjectStatus.NOT_ALLOWED; 233 } 234 }, Collections.<PsiElement>singletonList(object)); 235 } 236 237 public void analyzeFiles( 238 @NotNull Collection<JetFile> files, 239 @NotNull List<AnalyzerScriptParameter> scriptParameters) { 240 WritableScope scope = new WritableScopeImpl( 241 JetScope.EMPTY, moduleDescriptor, 242 new TraceBasedRedeclarationHandler(trace), "Root scope in analyzeNamespace"); 243 244 scope.changeLockLevel(WritableScope.LockLevel.BOTH); 245 246 NamespaceDescriptorImpl rootNs = namespaceFactory.createNamespaceDescriptorPathIfNeeded(FqName.ROOT); 247 248 // map "jet" namespace into KotlinBuiltIns 249 // @see DefaultModuleConfiguraiton#extendNamespaceScope 250 namespaceFactory.createNamespaceDescriptorPathIfNeeded(KotlinBuiltIns.getInstance().getBuiltInsPackageFqName()); 251 252 // Import a scope that contains all top-level namespaces that come from dependencies 253 // This makes the namespaces visible at all, does not import themselves 254 scope.importScope(rootNs.getMemberScope()); 255 256 scope.changeLockLevel(WritableScope.LockLevel.READING); 257 258 // dummy builder is used because "root" is module descriptor, 259 // namespaces added to module explicitly in 260 doProcess(scope, new NamespaceLikeBuilderDummy(), files); 261 } 262 263 264 public void prepareForTheNextReplLine() { 265 context.getScriptScopes().clear(); 266 context.getScripts().clear(); 267 } 268 269 270} 271 272