001    /*
002     * Copyright 2010-2016 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.kotlin.types;
018    
019    import kotlin.jvm.functions.Function1;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.kotlin.builtins.DefaultBuiltIns;
023    import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
024    import org.jetbrains.kotlin.descriptors.*;
025    import org.jetbrains.kotlin.descriptors.annotations.Annotations;
026    import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl;
027    import org.jetbrains.kotlin.descriptors.impl.ConstructorDescriptorImpl;
028    import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl;
029    import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
030    import org.jetbrains.kotlin.incremental.components.LookupLocation;
031    import org.jetbrains.kotlin.name.FqName;
032    import org.jetbrains.kotlin.name.Name;
033    import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap;
034    import org.jetbrains.kotlin.resolve.ImportPath;
035    import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
036    import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter;
037    import org.jetbrains.kotlin.resolve.scopes.MemberScope;
038    import org.jetbrains.kotlin.types.error.ErrorSimpleFunctionDescriptorImpl;
039    import org.jetbrains.kotlin.utils.Printer;
040    
041    import java.util.Collection;
042    import java.util.Collections;
043    import java.util.List;
044    import java.util.Set;
045    
046    import static kotlin.collections.CollectionsKt.emptyList;
047    import static kotlin.collections.CollectionsKt.joinToString;
048    
049    public class ErrorUtils {
050    
051        private static final ModuleDescriptor ERROR_MODULE;
052        static {
053            ERROR_MODULE = new ModuleDescriptor() {
054                @Nullable
055                @Override
056                public <T> T getCapability(@NotNull Capability<T> capability) {
057                    return null;
058                }
059    
060                @NotNull
061                @Override
062                public PlatformToKotlinClassMap getPlatformToKotlinClassMap() {
063                    throw new IllegalStateException("Should not be called!");
064                }
065    
066                @NotNull
067                @Override
068                public List<ImportPath> getDefaultImports() {
069                    return emptyList();
070                }
071    
072                @NotNull
073                @Override
074                public Annotations getAnnotations() {
075                    return Annotations.Companion.getEMPTY();
076                }
077    
078                @NotNull
079                @Override
080                public Collection<FqName> getSubPackagesOf(
081                        @NotNull FqName fqName, @NotNull Function1<? super Name, Boolean> nameFilter
082                ) {
083                    return emptyList();
084                }
085    
086                @NotNull
087                @Override
088                public Name getName() {
089                    return Name.special("<ERROR MODULE>");
090                }
091    
092                @NotNull
093                @Override
094                public PackageViewDescriptor getPackage(@NotNull FqName fqName) {
095                    throw new IllegalStateException("Should not be called!");
096                }
097    
098                @Override
099                public <R, D> R accept(@NotNull DeclarationDescriptorVisitor<R, D> visitor, D data) {
100                    return null;
101                }
102    
103                @Override
104                public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
105    
106                }
107    
108                @NotNull
109                @Override
110                public ModuleDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
111                    return this;
112                }
113    
114                @Override
115                public boolean isFriend(@NotNull ModuleDescriptor other) {
116                    return false;
117                }
118    
119                @NotNull
120                @Override
121                public DeclarationDescriptor getOriginal() {
122                    return this;
123                }
124    
125                @Nullable
126                @Override
127                public DeclarationDescriptor getContainingDeclaration() {
128                    return null;
129                }
130    
131                @NotNull
132                @Override
133                public KotlinBuiltIns getBuiltIns() {
134                    return DefaultBuiltIns.getInstance();
135                }
136            };
137        }
138    
139        public static boolean containsErrorType(@NotNull CallableDescriptor callableDescriptor) {
140            if (callableDescriptor instanceof FunctionDescriptor) {
141                return containsErrorType((FunctionDescriptor) callableDescriptor);
142            }
143            else {
144                return containsErrorType(callableDescriptor.getReturnType());
145            }
146        }
147    
148        public static boolean containsErrorType(@NotNull FunctionDescriptor function) {
149            if (containsErrorType(function.getReturnType())) {
150                return true;
151            }
152            ReceiverParameterDescriptor receiverParameter = function.getExtensionReceiverParameter();
153            if (receiverParameter != null && containsErrorType(receiverParameter.getType())) {
154                return true;
155            }
156            for (ValueParameterDescriptor parameter : function.getValueParameters()) {
157                if (containsErrorType(parameter.getType())) {
158                    return true;
159                }
160            }
161            for (TypeParameterDescriptor parameter : function.getTypeParameters()) {
162                for (KotlinType upperBound : parameter.getUpperBounds()) {
163                    if (containsErrorType(upperBound)) {
164                        return true;
165                    }
166                }
167            }
168    
169            return false;
170        }
171    
172        public static class ErrorScope implements MemberScope {
173            private final String debugMessage;
174    
175            private ErrorScope(@NotNull String debugMessage) {
176                this.debugMessage = debugMessage;
177            }
178    
179            @Nullable
180            @Override
181            public ClassifierDescriptor getContributedClassifier(@NotNull Name name, @NotNull LookupLocation location) {
182                return createErrorClass(name.asString());
183            }
184    
185            @NotNull
186            @Override
187            // TODO: Convert to Kotlin or add @JvmWildcard to MemberScope declarations
188            // method is covariantly overridden in Kotlin, but collections in Java are invariant
189            @SuppressWarnings({"unchecked"})
190            public Set getContributedVariables(@NotNull Name name, @NotNull LookupLocation location) {
191                return ERROR_PROPERTY_GROUP;
192            }
193    
194            @NotNull
195            @Override
196            // TODO: Convert to Kotlin or add @JvmWildcard to MemberScope declarations
197            // method is covariantly overridden in Kotlin, but collections in Java are invariant
198            @SuppressWarnings({"unchecked"})
199            public Set getContributedFunctions(@NotNull Name name, @NotNull LookupLocation location) {
200                return Collections.singleton(createErrorFunction(this));
201            }
202    
203            @NotNull
204            @Override
205            public Collection<DeclarationDescriptor> getContributedDescriptors(
206                    @NotNull DescriptorKindFilter kindFilter, @NotNull Function1<? super Name, Boolean> nameFilter
207            ) {
208                return Collections.emptyList();
209            }
210    
211            @Override
212            public String toString() {
213                return "ErrorScope{" + debugMessage + '}';
214            }
215    
216            @Override
217            public void printScopeStructure(@NotNull Printer p) {
218                p.println(getClass().getSimpleName(), ": ", debugMessage);
219            }
220        }
221    
222        private static class ThrowingScope implements MemberScope {
223            private final String debugMessage;
224    
225            private ThrowingScope(@NotNull String message) {
226                debugMessage = message;
227            }
228    
229            @Nullable
230            @Override
231            public ClassifierDescriptor getContributedClassifier(@NotNull Name name, @NotNull LookupLocation location) {
232                throw new IllegalStateException();
233            }
234    
235            @NotNull
236            @Override
237            @SuppressWarnings({"unchecked"}) // KT-9898 Impossible implement kotlin interface from java
238            public Collection getContributedVariables(@NotNull Name name, @NotNull LookupLocation location) {
239                throw new IllegalStateException();
240            }
241    
242            @NotNull
243            @Override
244            // TODO: Convert to Kotlin or add @JvmWildcard to MemberScope declarations
245            // method is covariantly overridden in Kotlin, but collections in Java are invariant
246            @SuppressWarnings({"unchecked"})
247            public Collection getContributedFunctions(@NotNull Name name, @NotNull LookupLocation location) {
248                throw new IllegalStateException();
249            }
250    
251            @NotNull
252            @Override
253            public Collection<DeclarationDescriptor> getContributedDescriptors(
254                    @NotNull DescriptorKindFilter kindFilter, @NotNull Function1<? super Name, Boolean> nameFilter
255            ) {
256                throw new IllegalStateException();
257            }
258    
259            @Override
260            public String toString() {
261                return "ThrowingScope{" + debugMessage + '}';
262            }
263    
264            @Override
265            public void printScopeStructure(@NotNull Printer p) {
266                p.println(getClass().getSimpleName(), ": ", debugMessage);
267            }
268        }
269    
270        private static final ErrorClassDescriptor ERROR_CLASS = new ErrorClassDescriptor(null);
271    
272        private static class ErrorClassDescriptor extends ClassDescriptorImpl {
273            public ErrorClassDescriptor(@Nullable String name) {
274                super(getErrorModule(), Name.special(name == null ? "<ERROR CLASS>" : "<ERROR CLASS: " + name + ">"),
275                      Modality.OPEN, ClassKind.CLASS, Collections.<KotlinType>emptyList(), SourceElement.NO_SOURCE);
276    
277                ConstructorDescriptorImpl errorConstructor = ConstructorDescriptorImpl.create(this, Annotations.Companion.getEMPTY(), true, SourceElement.NO_SOURCE);
278                errorConstructor.initialize(Collections.<ValueParameterDescriptor>emptyList(),
279                                            Visibilities.INTERNAL);
280                MemberScope memberScope = createErrorScope(getName().asString());
281                errorConstructor.setReturnType(
282                        new ErrorTypeImpl(
283                                createErrorTypeConstructorWithCustomDebugName("<ERROR>", this),
284                                memberScope
285                        )
286                );
287    
288                initialize(memberScope, Collections.<ConstructorDescriptor>singleton(errorConstructor), errorConstructor);
289            }
290    
291            @NotNull
292            @Override
293            public ClassDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
294                return this;
295            }
296    
297            @Override
298            public String toString() {
299                return getName().asString();
300            }
301    
302            @NotNull
303            @Override
304            public MemberScope getMemberScope(@NotNull List<? extends TypeProjection> typeArguments) {
305                return createErrorScope("Error scope for class " + getName() + " with arguments: " + typeArguments);
306            }
307    
308            @NotNull
309            @Override
310            public MemberScope getMemberScope(@NotNull TypeSubstitution typeSubstitution) {
311                return createErrorScope("Error scope for class " + getName() + " with arguments: " + typeSubstitution);
312            }
313        }
314    
315        @NotNull
316        public static ClassDescriptor createErrorClass(@NotNull String debugMessage) {
317            return new ErrorClassDescriptor(debugMessage);
318        }
319    
320        @NotNull
321        public static MemberScope createErrorScope(@NotNull String debugMessage) {
322            return createErrorScope(debugMessage, false);
323        }
324    
325        @NotNull
326        public static MemberScope createErrorScope(@NotNull String debugMessage, boolean throwExceptions) {
327            if (throwExceptions) {
328                return new ThrowingScope(debugMessage);
329            }
330            return new ErrorScope(debugMessage);
331        }
332    
333        // Do not move it into AbstractTypeConstructor.Companion because of cycle in initialization(see KT-13264)
334        public static final KotlinType ERROR_TYPE_FOR_LOOP_IN_SUPERTYPES = createErrorType("<LOOP IN SUPERTYPES>");
335    
336        private static final KotlinType ERROR_PROPERTY_TYPE = createErrorType("<ERROR PROPERTY TYPE>");
337        private static final PropertyDescriptor ERROR_PROPERTY = createErrorProperty();
338    
339        private static final Set<PropertyDescriptor> ERROR_PROPERTY_GROUP = Collections.singleton(ERROR_PROPERTY);
340    
341        @NotNull
342        private static PropertyDescriptorImpl createErrorProperty() {
343            PropertyDescriptorImpl descriptor = PropertyDescriptorImpl.create(
344                    ERROR_CLASS,
345                    Annotations.Companion.getEMPTY(),
346                    Modality.OPEN,
347                    Visibilities.INTERNAL,
348                    true,
349                    Name.special("<ERROR PROPERTY>"),
350                    CallableMemberDescriptor.Kind.DECLARATION,
351                    SourceElement.NO_SOURCE,
352                    /* lateInit = */ false,
353                    /* isConst = */ false
354            );
355            descriptor.setType(ERROR_PROPERTY_TYPE,
356                               Collections.<TypeParameterDescriptor>emptyList(),
357                               null,
358                               (KotlinType) null
359            );
360    
361            return descriptor;
362        }
363    
364        @NotNull
365        private static SimpleFunctionDescriptor createErrorFunction(@NotNull ErrorScope ownerScope) {
366            ErrorSimpleFunctionDescriptorImpl function = new ErrorSimpleFunctionDescriptorImpl(ERROR_CLASS, ownerScope);
367            function.initialize(
368                    null,
369                    null,
370                    Collections.<TypeParameterDescriptorImpl>emptyList(), // TODO
371                    Collections.<ValueParameterDescriptor>emptyList(), // TODO
372                    createErrorType("<ERROR FUNCTION RETURN TYPE>"),
373                    Modality.OPEN,
374                    Visibilities.INTERNAL
375            );
376            return function;
377        }
378    
379        @NotNull
380        public static KotlinType createErrorType(@NotNull String debugMessage) {
381            return createErrorTypeWithArguments(debugMessage, Collections.<TypeProjection>emptyList());
382        }
383    
384        @NotNull
385        public static KotlinType createErrorTypeWithCustomDebugName(@NotNull String debugName) {
386            return createErrorTypeWithCustomConstructor(debugName, createErrorTypeConstructorWithCustomDebugName(debugName));
387        }
388    
389        @NotNull
390        public static KotlinType createErrorTypeWithCustomConstructor(@NotNull String debugName, @NotNull TypeConstructor typeConstructor) {
391            return new ErrorTypeImpl(typeConstructor, createErrorScope(debugName));
392        }
393    
394        @NotNull
395        public static KotlinType createErrorTypeWithArguments(@NotNull String debugMessage, @NotNull List<TypeProjection> arguments) {
396            return new ErrorTypeImpl(createErrorTypeConstructor(debugMessage), createErrorScope(debugMessage), arguments);
397        }
398    
399        @NotNull
400        public static TypeConstructor createErrorTypeConstructor(@NotNull String debugMessage) {
401            return createErrorTypeConstructorWithCustomDebugName("[ERROR : " + debugMessage + "]", ERROR_CLASS);
402        }
403    
404        @NotNull
405        public static TypeConstructor createErrorTypeConstructorWithCustomDebugName(@NotNull String debugName) {
406            return createErrorTypeConstructorWithCustomDebugName(debugName, ERROR_CLASS);
407        }
408    
409        @NotNull
410        private static TypeConstructor createErrorTypeConstructorWithCustomDebugName(
411                @NotNull final String debugName, @NotNull final ErrorClassDescriptor errorClass
412        ) {
413            return new TypeConstructor() {
414                @NotNull
415                @Override
416                public List<TypeParameterDescriptor> getParameters() {
417                    return emptyList();
418                }
419    
420                @NotNull
421                @Override
422                public Collection<KotlinType> getSupertypes() {
423                    return emptyList();
424                }
425    
426                @Override
427                public boolean isFinal() {
428                    return false;
429                }
430    
431                @Override
432                public boolean isDenotable() {
433                    return false;
434                }
435    
436                @Nullable
437                @Override
438                public ClassifierDescriptor getDeclarationDescriptor() {
439                    return errorClass;
440                }
441    
442                @NotNull
443                @Override
444                public KotlinBuiltIns getBuiltIns() {
445                    return DefaultBuiltIns.getInstance();
446                }
447    
448                @NotNull
449                @Override
450                public Annotations getAnnotations() {
451                    return Annotations.Companion.getEMPTY();
452                }
453    
454                @Override
455                public String toString() {
456                    return debugName;
457                }
458            };
459        }
460    
461        public static boolean containsErrorType(@Nullable KotlinType type) {
462            if (type == null) return false;
463            if (type.isError()) return true;
464            for (TypeProjection projection : type.getArguments()) {
465                if (!projection.isStarProjection() && containsErrorType(projection.getType())) return true;
466            }
467            return false;
468        }
469    
470        public static boolean isError(@NotNull DeclarationDescriptor candidate) {
471            return isErrorClass(candidate) || isErrorClass(candidate.getContainingDeclaration()) || candidate == ERROR_MODULE;
472        }
473    
474        private static boolean isErrorClass(@Nullable DeclarationDescriptor candidate) {
475            return candidate instanceof ErrorClassDescriptor;
476        }
477    
478        @NotNull
479        public static TypeParameterDescriptor createErrorTypeParameter(int index, @NotNull String debugMessage) {
480            return TypeParameterDescriptorImpl.createWithDefaultBound(
481                    ERROR_CLASS,
482                    Annotations.Companion.getEMPTY(),
483                    false,
484                    Variance.INVARIANT,
485                    Name.special("<ERROR: " + debugMessage + ">"),
486                    index
487            );
488        }
489    
490        private static class ErrorTypeImpl implements KotlinType {
491            private final TypeConstructor constructor;
492            private final MemberScope memberScope;
493            private final List<TypeProjection> arguments;
494    
495            private ErrorTypeImpl(
496                    @NotNull TypeConstructor constructor,
497                    @NotNull MemberScope memberScope,
498                    @NotNull List<TypeProjection> arguments
499            ) {
500                this.constructor = constructor;
501                this.memberScope = memberScope;
502                this.arguments = arguments;
503            }
504    
505            private ErrorTypeImpl(@NotNull TypeConstructor constructor, @NotNull MemberScope memberScope) {
506                this(constructor, memberScope, Collections.<TypeProjection>emptyList());
507            }
508    
509            @NotNull
510            @Override
511            public TypeConstructor getConstructor() {
512                return constructor;
513            }
514    
515            @NotNull
516            @Override
517            public List<TypeProjection> getArguments() {
518                return arguments;
519            }
520    
521            @NotNull
522            @Override
523            public TypeSubstitution getSubstitution() {
524                return TypeConstructorSubstitution.create(constructor, arguments);
525            }
526    
527            @Override
528            public boolean isMarkedNullable() {
529                return false;
530            }
531    
532            @NotNull
533            @Override
534            public MemberScope getMemberScope() {
535                return memberScope;
536            }
537    
538            @Override
539            public boolean isError() {
540                return true;
541            }
542    
543            @NotNull
544            @Override
545            public Annotations getAnnotations() {
546                return Annotations.Companion.getEMPTY();
547            }
548    
549            @Nullable
550            @Override
551            public <T extends TypeCapability> T getCapability(@NotNull Class<T> capabilityClass) {
552                return null;
553            }
554    
555            @NotNull
556            @Override
557            public TypeCapabilities getCapabilities() {
558                return TypeCapabilities.NONE.INSTANCE;
559            }
560    
561            @Override
562            public String toString() {
563                return constructor.toString() + (arguments.isEmpty() ? "" : joinToString(arguments, ", ", "<", ">", -1, "...", null));
564            }
565        }
566    
567        @NotNull
568        public static ModuleDescriptor getErrorModule() {
569            return ERROR_MODULE;
570        }
571    
572        public static boolean isUninferredParameter(@Nullable KotlinType type) {
573            return type != null && type.getConstructor() instanceof UninferredParameterTypeConstructor;
574        }
575    
576        public static boolean containsUninferredParameter(@Nullable KotlinType type) {
577            return TypeUtils.contains(type, new Function1<KotlinType, Boolean>() {
578                @Override
579                public Boolean invoke(KotlinType argumentType) {
580                    return isUninferredParameter(argumentType);
581                }
582            });
583        }
584    
585        @NotNull
586        public static KotlinType createUninferredParameterType(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
587            return createErrorTypeWithCustomConstructor("Scope for error type for not inferred parameter: " + typeParameterDescriptor.getName(),
588                                                        new UninferredParameterTypeConstructor(typeParameterDescriptor));
589        }
590    
591        public static class UninferredParameterTypeConstructor implements TypeConstructor {
592            private final TypeParameterDescriptor typeParameterDescriptor;
593            private final TypeConstructor errorTypeConstructor;
594    
595            private UninferredParameterTypeConstructor(@NotNull TypeParameterDescriptor descriptor) {
596                typeParameterDescriptor = descriptor;
597                errorTypeConstructor = createErrorTypeConstructorWithCustomDebugName("CANT_INFER_TYPE_PARAMETER: " + descriptor.getName());
598            }
599    
600            @NotNull
601            public TypeParameterDescriptor getTypeParameterDescriptor() {
602                return typeParameterDescriptor;
603            }
604    
605            @NotNull
606            @Override
607            public List<TypeParameterDescriptor> getParameters() {
608                return errorTypeConstructor.getParameters();
609            }
610    
611            @NotNull
612            @Override
613            public Collection<KotlinType> getSupertypes() {
614                return errorTypeConstructor.getSupertypes();
615            }
616    
617            @Override
618            public boolean isFinal() {
619                return errorTypeConstructor.isFinal();
620            }
621    
622            @Override
623            public boolean isDenotable() {
624                return errorTypeConstructor.isDenotable();
625            }
626    
627            @Nullable
628            @Override
629            public ClassifierDescriptor getDeclarationDescriptor() {
630                return errorTypeConstructor.getDeclarationDescriptor();
631            }
632    
633            @NotNull
634            @Override
635            public Annotations getAnnotations() {
636                return errorTypeConstructor.getAnnotations();
637            }
638    
639            @NotNull
640            @Override
641            public KotlinBuiltIns getBuiltIns() {
642                return DescriptorUtilsKt.getBuiltIns(typeParameterDescriptor);
643            }
644        }
645    
646        private ErrorUtils() {}
647    }