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; 018 019 import com.google.common.collect.Lists; 020 import com.intellij.openapi.util.Key; 021 import org.jetbrains.annotations.NotNull; 022 import org.jetbrains.jet.lang.descriptors.ClassDescriptor; 023 import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor; 024 import org.jetbrains.jet.lang.descriptors.ScriptDescriptor; 025 import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; 026 import org.jetbrains.jet.lang.descriptors.annotations.Annotations; 027 import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl; 028 import org.jetbrains.jet.lang.parsing.JetScriptDefinition; 029 import org.jetbrains.jet.lang.parsing.JetScriptDefinitionProvider; 030 import org.jetbrains.jet.lang.psi.JetFile; 031 import org.jetbrains.jet.lang.psi.JetPackageDirective; 032 import org.jetbrains.jet.lang.psi.JetScript; 033 import org.jetbrains.jet.lang.resolve.name.FqName; 034 import org.jetbrains.jet.lang.resolve.name.Name; 035 import org.jetbrains.jet.lang.resolve.scopes.JetScope; 036 import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler; 037 import org.jetbrains.jet.lang.resolve.scopes.WritableScope; 038 import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; 039 import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolver; 040 import org.jetbrains.jet.lang.types.JetType; 041 import org.jetbrains.jet.lang.types.TypeUtils; 042 import org.jetbrains.jet.lang.types.ref.JetTypeName; 043 044 import javax.inject.Inject; 045 import java.util.ArrayList; 046 import java.util.List; 047 import java.util.Map; 048 049 public class ScriptHeaderResolver { 050 051 public static final Key<Integer> PRIORITY_KEY = Key.create(JetScript.class.getName() + ".priority"); 052 053 @NotNull 054 private MutablePackageFragmentProvider packageFragmentProvider; 055 @NotNull 056 private DependencyClassByQualifiedNameResolver dependencyClassByQualifiedNameResolver; 057 @NotNull 058 private BindingTrace trace; 059 060 @Inject 061 public void setPackageFragmentProvider(@NotNull MutablePackageFragmentProvider packageFragmentProvider) { 062 this.packageFragmentProvider = packageFragmentProvider; 063 } 064 065 @Inject 066 public void setDependencyClassByQualifiedNameResolver(@NotNull DependencyClassByQualifiedNameResolver dependencyClassByQualifiedNameResolver) { 067 this.dependencyClassByQualifiedNameResolver = dependencyClassByQualifiedNameResolver; 068 } 069 070 @Inject 071 public void setTrace(@NotNull BindingTrace trace) { 072 this.trace = trace; 073 } 074 075 076 @NotNull 077 private ClassDescriptor resolveClass(@NotNull FqName className) { 078 ClassDescriptor classDescriptor = dependencyClassByQualifiedNameResolver.resolveClass(className); 079 if (classDescriptor == null) { 080 throw new IllegalStateException("dependency class not found by name: " + className); 081 } 082 return classDescriptor; 083 } 084 085 @NotNull 086 public JetType resolveTypeName(@NotNull JetTypeName typeName) { 087 List<JetType> typeArguments = new ArrayList<JetType>(); 088 for (JetTypeName typeArgumentName : typeName.getArguments()) { 089 typeArguments.add(resolveTypeName(typeArgumentName)); 090 } 091 ClassDescriptor classDescriptor = resolveClass(typeName.getClassName()); 092 return TypeUtils.substituteParameters(classDescriptor, typeArguments); 093 } 094 095 096 @NotNull 097 private ValueParameterDescriptor resolveScriptParameter( 098 @NotNull AnalyzerScriptParameter scriptParameter, 099 int index, 100 @NotNull ScriptDescriptor script) { 101 JetType type = resolveTypeName(scriptParameter.getType()); 102 return new ValueParameterDescriptorImpl(script, index, Annotations.EMPTY, scriptParameter.getName(), type, false, null); 103 } 104 105 public void processScriptHierarchy(@NotNull TopDownAnalysisContext c, @NotNull JetScript script, @NotNull JetScope outerScope) { 106 JetFile file = (JetFile) script.getContainingFile(); 107 JetPackageDirective packageDirective = file.getPackageDirective(); 108 FqName fqName = packageDirective != null ? new FqName(packageDirective.getQualifiedName()) : FqName.ROOT; 109 PackageFragmentDescriptor ns = packageFragmentProvider.getOrCreateFragment(fqName); 110 111 Integer priority = script.getUserData(PRIORITY_KEY); 112 if (priority == null) { 113 priority = 0; 114 } 115 116 Name className = new FqName(ScriptNameUtil.classNameForScript((JetFile) script.getContainingFile()).replace('/', '.')).shortName(); 117 ScriptDescriptor scriptDescriptor = new ScriptDescriptor(ns, priority, outerScope, className); 118 119 //WriteThroughScope scriptScope = new WriteThroughScope( 120 // outerScope, ns.getMemberScope(), new TraceBasedRedeclarationHandler(trace)); 121 WritableScopeImpl scriptScope = new WritableScopeImpl(outerScope, scriptDescriptor, RedeclarationHandler.DO_NOTHING, "script"); 122 scriptScope.changeLockLevel(WritableScope.LockLevel.BOTH); 123 124 c.getScriptScopes().put(script, scriptScope); 125 c.getScripts().put(script, scriptDescriptor); 126 127 trace.record(BindingContext.SCRIPT, script, scriptDescriptor); 128 129 ((WritableScope)outerScope).addClassifierDescriptor(scriptDescriptor.getClassDescriptor()); 130 } 131 132 public void resolveScriptDeclarations(@NotNull TopDownAnalysisContext c) { 133 for (Map.Entry<JetScript, ScriptDescriptor> e : c.getScripts().entrySet()) { 134 JetScript declaration = e.getKey(); 135 ScriptDescriptor descriptor = e.getValue(); 136 WritableScope scope = c.getScriptScopes().get(declaration); 137 138 List<ValueParameterDescriptor> valueParameters = Lists.newArrayList(); 139 140 scope.setImplicitReceiver(descriptor.getThisAsReceiverParameter()); 141 142 JetFile file = (JetFile) declaration.getContainingFile(); 143 JetScriptDefinition scriptDefinition = JetScriptDefinitionProvider.getInstance(file.getProject()).findScriptDefinition(file); 144 145 int index = 0; 146 List<AnalyzerScriptParameter> scriptParameters = !scriptDefinition.getScriptParameters().isEmpty() 147 ? scriptDefinition.getScriptParameters() 148 : c.getTopDownAnalysisParameters().getScriptParameters(); 149 150 for (AnalyzerScriptParameter scriptParameter : scriptParameters) { 151 ValueParameterDescriptor parameter = resolveScriptParameter(scriptParameter, index, descriptor); 152 valueParameters.add(parameter); 153 scope.addVariableDescriptor(parameter); 154 ++index; 155 } 156 157 descriptor.setValueParameters(valueParameters); 158 } 159 } 160 }