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.ScriptDescriptor;
024 import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
025 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
026 import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorImpl;
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.JetNamespaceHeader;
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.Collections;
047 import java.util.List;
048 import java.util.Map;
049
050 public class ScriptHeaderResolver {
051
052 public static final Key<Integer> PRIORITY_KEY = Key.create(JetScript.class.getName() + ".priority");
053
054 @NotNull
055 private NamespaceFactory namespaceFactory;
056 @NotNull
057 private DependencyClassByQualifiedNameResolver dependencyClassByQualifiedNameResolver;
058 @NotNull
059 private TopDownAnalysisContext context;
060 @NotNull
061 private BindingTrace trace;
062 @NotNull
063 private TopDownAnalysisParameters topDownAnalysisParameters;
064
065 @Inject
066 public void setNamespaceFactory(@NotNull NamespaceFactory namespaceFactory) {
067 this.namespaceFactory = namespaceFactory;
068 }
069
070 @Inject
071 public void setDependencyClassByQualifiedNameResolver(@NotNull DependencyClassByQualifiedNameResolver dependencyClassByQualifiedNameResolver) {
072 this.dependencyClassByQualifiedNameResolver = dependencyClassByQualifiedNameResolver;
073 }
074
075 @Inject
076 public void setContext(@NotNull TopDownAnalysisContext context) {
077 this.context = context;
078 }
079
080 @Inject
081 public void setTrace(@NotNull BindingTrace trace) {
082 this.trace = trace;
083 }
084
085 @Inject
086 public void setTopDownAnalysisParameters(@NotNull TopDownAnalysisParameters topDownAnalysisParameters) {
087 this.topDownAnalysisParameters = topDownAnalysisParameters;
088 }
089
090
091 @NotNull
092 private ClassDescriptor resolveClass(@NotNull FqName className) {
093 ClassDescriptor classDescriptor = dependencyClassByQualifiedNameResolver.resolveClass(className);
094 if (classDescriptor == null) {
095 throw new IllegalStateException("dependency class not found by name: " + className);
096 }
097 return classDescriptor;
098 }
099
100 @NotNull
101 public JetType resolveTypeName(@NotNull JetTypeName typeName) {
102 List<JetType> typeArguments = new ArrayList<JetType>();
103 for (JetTypeName typeArgumentName : typeName.getArguments()) {
104 typeArguments.add(resolveTypeName(typeArgumentName));
105 }
106 ClassDescriptor classDescriptor = resolveClass(typeName.getClassName());
107 return TypeUtils.substituteParameters(classDescriptor, typeArguments);
108 }
109
110
111 @NotNull
112 private ValueParameterDescriptor resolveScriptParameter(
113 @NotNull AnalyzerScriptParameter scriptParameter,
114 int index,
115 @NotNull ScriptDescriptor script) {
116 JetType type = resolveTypeName(scriptParameter.getType());
117 return new ValueParameterDescriptorImpl(script, index, Collections.<AnnotationDescriptor>emptyList(), scriptParameter.getName(), type, false, null);
118 }
119
120 public void processScriptHierarchy(@NotNull JetScript script, @NotNull JetScope outerScope) {
121 JetFile file = (JetFile) script.getContainingFile();
122 JetNamespaceHeader namespaceHeader = file.getNamespaceHeader();
123 FqName fqName = namespaceHeader != null ? new FqName(namespaceHeader.getQualifiedName()) : FqName.ROOT;
124 NamespaceDescriptorImpl ns = namespaceFactory.createNamespaceDescriptorPathIfNeeded(fqName);
125
126 Integer priority = script.getUserData(PRIORITY_KEY);
127 if (priority == null) {
128 priority = 0;
129 }
130
131 Name className = new FqName(ScriptNameUtil.classNameForScript((JetFile) script.getContainingFile()).replace('/', '.')).shortName();
132 ScriptDescriptor scriptDescriptor = new ScriptDescriptor(ns, priority, outerScope, className);
133
134 //WriteThroughScope scriptScope = new WriteThroughScope(
135 // outerScope, ns.getMemberScope(), new TraceBasedRedeclarationHandler(trace));
136 WritableScopeImpl scriptScope = new WritableScopeImpl(outerScope, scriptDescriptor, RedeclarationHandler.DO_NOTHING, "script");
137 scriptScope.changeLockLevel(WritableScope.LockLevel.BOTH);
138
139 context.getScriptScopes().put(script, scriptScope);
140 context.getScripts().put(script, scriptDescriptor);
141
142 trace.record(BindingContext.SCRIPT, script, scriptDescriptor);
143
144 ((WritableScope)outerScope).addClassifierDescriptor(scriptDescriptor.getClassDescriptor());
145 }
146
147 public void resolveScriptDeclarations() {
148 for (Map.Entry<JetScript, ScriptDescriptor> e : context.getScripts().entrySet()) {
149 JetScript declaration = e.getKey();
150 ScriptDescriptor descriptor = e.getValue();
151 WritableScope scope = context.getScriptScopes().get(declaration);
152
153 List<ValueParameterDescriptor> valueParameters = Lists.newArrayList();
154
155 scope.setImplicitReceiver(descriptor.getThisAsReceiverParameter());
156
157 JetFile file = (JetFile) declaration.getContainingFile();
158 JetScriptDefinition scriptDefinition = JetScriptDefinitionProvider.getInstance(file.getProject()).findScriptDefinition(file);
159
160 int index = 0;
161 List<AnalyzerScriptParameter> scriptParameters = !scriptDefinition.getScriptParameters().isEmpty()
162 ? scriptDefinition.getScriptParameters()
163 : topDownAnalysisParameters.getScriptParameters();
164
165 for (AnalyzerScriptParameter scriptParameter : scriptParameters) {
166 ValueParameterDescriptor parameter = resolveScriptParameter(scriptParameter, index, descriptor);
167 valueParameters.add(parameter);
168 scope.addVariableDescriptor(parameter);
169 ++index;
170 }
171
172 descriptor.setValueParameters(valueParameters);
173 }
174 }
175 }