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.types;
018
019import org.jetbrains.annotations.NotNull;
020import org.jetbrains.annotations.Nullable;
021import org.jetbrains.jet.lang.ModuleConfiguration;
022import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
023import org.jetbrains.jet.lang.descriptors.*;
024import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
025import org.jetbrains.jet.lang.descriptors.impl.*;
026import org.jetbrains.jet.lang.resolve.ImportPath;
027import org.jetbrains.jet.lang.resolve.name.LabelName;
028import org.jetbrains.jet.lang.resolve.name.Name;
029import org.jetbrains.jet.lang.resolve.scopes.JetScope;
030import org.jetbrains.jet.lang.types.error.ErrorSimpleFunctionDescriptorImpl;
031import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
032
033import java.util.*;
034
035public class ErrorUtils {
036
037    private static final ModuleDescriptor ERROR_MODULE;
038    static {
039        ModuleDescriptorImpl module = new ModuleDescriptorImpl(
040                Name.special("<ERROR MODULE>"),
041                Collections.<ImportPath>emptyList(),
042                PlatformToKotlinClassMap.EMPTY
043        );
044        module.setModuleConfiguration(ModuleConfiguration.EMPTY);
045        ERROR_MODULE = module;
046    }
047
048
049    public static class ErrorScope implements JetScope {
050
051        private final String debugMessage;
052
053        private ErrorScope(String debugMessage) {
054            this.debugMessage = debugMessage;
055        }
056
057        @Override
058        public ClassifierDescriptor getClassifier(@NotNull Name name) {
059            return ERROR_CLASS;
060        }
061
062        @Override
063        public ClassDescriptor getObjectDescriptor(@NotNull Name name) {
064            return ERROR_CLASS;
065        }
066
067        @NotNull
068        @Override
069        public Set<ClassDescriptor> getObjectDescriptors() {
070            return Collections.emptySet();
071        }
072
073        @NotNull
074        @Override
075        public Set<VariableDescriptor> getProperties(@NotNull Name name) {
076            return ERROR_PROPERTY_GROUP;
077        }
078
079        @Override
080        public VariableDescriptor getLocalVariable(@NotNull Name name) {
081            return ERROR_PROPERTY;
082        }
083
084        @Override
085        public NamespaceDescriptor getNamespace(@NotNull Name name) {
086            return null; // TODO : review
087        }
088
089        @NotNull
090        @Override
091        public List<ReceiverParameterDescriptor> getImplicitReceiversHierarchy() {
092            return Collections.emptyList();
093        }
094
095        @NotNull
096        @Override
097        public Set<FunctionDescriptor> getFunctions(@NotNull Name name) {
098            return Collections.<FunctionDescriptor>singleton(createErrorFunction(this));
099        }
100
101        @NotNull
102        @Override
103        public DeclarationDescriptor getContainingDeclaration() {
104            return ERROR_MODULE;
105        }
106
107        @NotNull
108        @Override
109        public Collection<DeclarationDescriptor> getDeclarationsByLabel(LabelName labelName) {
110            return Collections.emptyList();
111        }
112
113        @Override
114        public PropertyDescriptor getPropertyByFieldReference(@NotNull Name fieldName) {
115            return null; // TODO : review
116        }
117
118        @NotNull
119        @Override
120        public Collection<DeclarationDescriptor> getAllDescriptors() {
121            return Collections.emptyList();
122        }
123
124        @NotNull
125        @Override
126        public Collection<DeclarationDescriptor> getOwnDeclaredDescriptors() {
127            return Collections.emptyList();
128        }
129
130        @Override
131        public String toString() {
132            return "ErrorScope{" + debugMessage + '}';
133        }
134    }
135
136    private static class ThrowingScope implements JetScope {
137        private final String debugMessage;
138
139        private ThrowingScope(String message) {
140            debugMessage = message;
141        }
142
143        @Nullable
144        @Override
145        public ClassifierDescriptor getClassifier(@NotNull Name name) {
146            throw new IllegalStateException();
147        }
148
149        @Nullable
150        @Override
151        public ClassDescriptor getObjectDescriptor(@NotNull Name name) {
152            throw new IllegalStateException();
153        }
154
155        @NotNull
156        @Override
157        public Collection<ClassDescriptor> getObjectDescriptors() {
158            throw new IllegalStateException();
159        }
160
161        @Nullable
162        @Override
163        public NamespaceDescriptor getNamespace(@NotNull Name name) {
164            throw new IllegalStateException();
165        }
166
167        @NotNull
168        @Override
169        public Collection<VariableDescriptor> getProperties(@NotNull Name name) {
170            throw new IllegalStateException();
171        }
172
173        @Nullable
174        @Override
175        public VariableDescriptor getLocalVariable(@NotNull Name name) {
176            throw new IllegalStateException();
177        }
178
179        @NotNull
180        @Override
181        public Collection<FunctionDescriptor> getFunctions(@NotNull Name name) {
182            throw new IllegalStateException();
183        }
184
185        @NotNull
186        @Override
187        public DeclarationDescriptor getContainingDeclaration() {
188            return ERROR_MODULE;
189        }
190
191        @NotNull
192        @Override
193        public Collection<DeclarationDescriptor> getDeclarationsByLabel(@NotNull LabelName labelName) {
194            throw new IllegalStateException();
195        }
196
197        @Nullable
198        @Override
199        public PropertyDescriptor getPropertyByFieldReference(@NotNull Name fieldName) {
200            throw new IllegalStateException();
201        }
202
203        @NotNull
204        @Override
205        public Collection<DeclarationDescriptor> getAllDescriptors() {
206            throw new IllegalStateException();
207        }
208
209        @NotNull
210        @Override
211        public List<ReceiverParameterDescriptor> getImplicitReceiversHierarchy() {
212            throw new IllegalStateException();
213        }
214
215        @NotNull
216        @Override
217        public Collection<DeclarationDescriptor> getOwnDeclaredDescriptors() {
218            throw new IllegalStateException();
219        }
220
221        @Override
222        public String toString() {
223            return "ThrowingScope{" + debugMessage + '}';
224        }
225    }
226
227    private static final ClassDescriptorImpl ERROR_CLASS = new ClassDescriptorImpl(ERROR_MODULE, Collections.<AnnotationDescriptor>emptyList(), Modality.OPEN, Name.special("<ERROR CLASS>")) {
228        @NotNull
229        @Override
230        public Collection<ConstructorDescriptor> getConstructors() {
231            return ERROR_CONSTRUCTOR_GROUP;
232        }
233
234        @NotNull
235        @Override
236        public Modality getModality() {
237            return Modality.OPEN;
238        }
239
240        @NotNull
241        @Override
242        public ClassDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
243            return ERROR_CLASS;
244        }
245    };
246
247    private static final Set<ConstructorDescriptor> ERROR_CONSTRUCTOR_GROUP = Collections.singleton(createErrorConstructor(0, Collections.<JetType>emptyList()));
248    private static final ConstructorDescriptor ERROR_CONSTRUCTOR = new ConstructorDescriptorImpl(ERROR_CLASS, Collections.<AnnotationDescriptor>emptyList(), true);
249
250    static {
251        ERROR_CLASS.initialize(
252            true, Collections.<TypeParameterDescriptor>emptyList(), Collections.<JetType>emptyList(), createErrorScope("ERROR_CLASS"), ERROR_CONSTRUCTOR_GROUP,
253            ERROR_CONSTRUCTOR, false);
254    }
255
256    public static JetScope createErrorScope(String debugMessage) {
257        return createErrorScope(debugMessage, false);
258    }
259
260    public static JetScope createErrorScope(String debugMessage, boolean throwExceptions) {
261        if (throwExceptions) {
262            return new ThrowingScope(debugMessage);
263        }
264        return new ErrorScope(debugMessage);
265    }
266
267    private static final JetType ERROR_PROPERTY_TYPE = createErrorType("<ERROR PROPERTY TYPE>");
268    private static final VariableDescriptor ERROR_PROPERTY = new PropertyDescriptorImpl(
269            ERROR_CLASS,
270            Collections.<AnnotationDescriptor>emptyList(),
271            Modality.OPEN,
272            Visibilities.INTERNAL,
273            true,
274            null,
275            ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER,
276            Name.special("<ERROR PROPERTY>"),
277            ERROR_PROPERTY_TYPE,
278            CallableMemberDescriptor.Kind.DECLARATION);
279    private static final Set<VariableDescriptor> ERROR_PROPERTY_GROUP = Collections.singleton(ERROR_PROPERTY);
280
281    private static SimpleFunctionDescriptor createErrorFunction(ErrorScope ownerScope) {
282        ErrorSimpleFunctionDescriptorImpl function = new ErrorSimpleFunctionDescriptorImpl(ownerScope);
283        function.initialize(
284                null,
285                ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER,
286                Collections.<TypeParameterDescriptorImpl>emptyList(), // TODO
287                Collections.<ValueParameterDescriptor>emptyList(), // TODO
288                createErrorType("<ERROR FUNCTION RETURN TYPE>"),
289                Modality.OPEN,
290                Visibilities.INTERNAL,
291                /*isInline = */ false
292        );
293        return function;
294    }
295
296    public static ConstructorDescriptor createErrorConstructor(int typeParameterCount, List<JetType> positionedValueParameterTypes) {
297        ConstructorDescriptorImpl r = new ConstructorDescriptorImpl(ERROR_CLASS, Collections.<AnnotationDescriptor>emptyList(), false);
298        r.initialize(
299                Collections.<TypeParameterDescriptor>emptyList(), // TODO
300                Collections.<ValueParameterDescriptor>emptyList(), // TODO
301                Visibilities.INTERNAL
302        );
303        r.setReturnType(createErrorType("<ERROR RETURN TYPE>"));
304        return r;
305    }
306
307    private static final JetType ERROR_PARAMETER_TYPE = createErrorType("<ERROR VALUE_PARAMETER TYPE>");
308    private static List<ValueParameterDescriptor> getValueParameters(FunctionDescriptor functionDescriptor, List<JetType> argumentTypes) {
309        List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
310        for (int i = 0, argumentTypesSize = argumentTypes.size(); i < argumentTypesSize; i++) {
311            result.add(new ValueParameterDescriptorImpl(
312                    functionDescriptor,
313                    i,
314                    Collections.<AnnotationDescriptor>emptyList(),
315                    Name.special("<ERROR VALUE_PARAMETER>"),
316                    ERROR_PARAMETER_TYPE,
317                    false,
318                    null));
319        }
320        return result;
321    }
322
323    @NotNull
324    public static JetType createErrorType(String debugMessage) {
325        return createErrorType(debugMessage, createErrorScope(debugMessage));
326    }
327
328    private static JetType createErrorType(String debugMessage, JetScope memberScope) {
329        return createErrorTypeWithCustomDebugName(memberScope, "[ERROR : " + debugMessage + "]");
330    }
331
332    @NotNull
333    public static JetType createErrorTypeWithCustomDebugName(String debugName) {
334        return createErrorTypeWithCustomDebugName(createErrorScope(debugName), debugName);
335    }
336
337    private static JetType createErrorTypeWithCustomDebugName(JetScope memberScope, String debugName) {
338        return new ErrorTypeImpl(new TypeConstructorImpl(ERROR_CLASS, Collections.<AnnotationDescriptor>emptyList(), false, debugName, Collections.<TypeParameterDescriptorImpl>emptyList(), Collections.singleton(KotlinBuiltIns.getInstance().getAnyType())), memberScope);
339    }
340
341    public static JetType createWrongVarianceErrorType(TypeProjection value) {
342        return createErrorType(value + " is not allowed here", value.getType().getMemberScope());
343    }
344
345    public static ClassifierDescriptor getErrorClass() {
346        return ERROR_CLASS;
347    }
348
349    public static boolean isError(@NotNull TypeConstructor typeConstructor) {
350        return typeConstructor == ERROR_CLASS.getTypeConstructor();
351    }
352
353    public static boolean isErrorType(@NotNull JetType type) {
354        return type != TypeUtils.NO_EXPECTED_TYPE && !(type instanceof NamespaceType) &&
355               (
356                    (type instanceof DeferredType && (((DeferredType) type).getActualType() == null
357                                                      || isErrorType(((DeferredType) type).getActualType()))) ||
358                    type instanceof ErrorTypeImpl ||
359                    isError(type.getConstructor())
360               );
361    }
362
363    public static boolean containsErrorType(@Nullable JetType type) {
364        if (type == null) return false;
365        if (type instanceof NamespaceType) return false;
366        if (isErrorType(type)) return true;
367        for (TypeProjection projection : type.getArguments()) {
368            if (containsErrorType(projection.getType())) return true;
369        }
370        return false;
371    }
372
373    public static boolean isError(@NotNull DeclarationDescriptor candidate) {
374        return candidate == getErrorClass() || candidate.getContainingDeclaration() == getErrorClass() || candidate == ERROR_MODULE;
375    }
376
377    private static class ErrorTypeImpl implements JetType {
378
379        private final TypeConstructor constructor;
380
381        private final JetScope memberScope;
382        private ErrorTypeImpl(TypeConstructor constructor, JetScope memberScope) {
383            this.constructor = constructor;
384            this.memberScope = memberScope;
385        }
386
387        @NotNull
388        @Override
389        public TypeConstructor getConstructor() {
390            return constructor;
391        }
392
393        @NotNull
394        @Override
395        public List<TypeProjection> getArguments() {
396            return Collections.emptyList();
397        }
398
399        @Override
400        public boolean isNullable() {
401            return false;
402        }
403
404        @NotNull
405        @Override
406        public JetScope getMemberScope() {
407            return memberScope;
408        }
409
410        @Override
411        public List<AnnotationDescriptor> getAnnotations() {
412            return Collections.emptyList();
413        }
414
415        @Override
416        public String toString() {
417            return constructor.toString();
418        }
419    }
420
421    public static ModuleDescriptor getErrorModule() {
422        return ERROR_MODULE;
423    }
424
425    private ErrorUtils() {}
426}