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