001    /*
002     * Copyright 2010-2015 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.CollectionsKt.emptyList;
047    import static kotlin.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, ? extends 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 FunctionDescriptor function) {
140            if (containsErrorType(function.getReturnType())) {
141                return true;
142            }
143            ReceiverParameterDescriptor receiverParameter = function.getExtensionReceiverParameter();
144            if (receiverParameter != null && containsErrorType(receiverParameter.getType())) {
145                return true;
146            }
147            for (ValueParameterDescriptor parameter : function.getValueParameters()) {
148                if (containsErrorType(parameter.getType())) {
149                    return true;
150                }
151            }
152            for (TypeParameterDescriptor parameter : function.getTypeParameters()) {
153                for (KotlinType upperBound : parameter.getUpperBounds()) {
154                    if (containsErrorType(upperBound)) {
155                        return true;
156                    }
157                }
158            }
159    
160            return false;
161        }
162    
163        public static class ErrorScope implements MemberScope {
164            private final String debugMessage;
165    
166            private ErrorScope(@NotNull String debugMessage) {
167                this.debugMessage = debugMessage;
168            }
169    
170            @Nullable
171            @Override
172            public ClassifierDescriptor getContributedClassifier(@NotNull Name name, @NotNull LookupLocation location) {
173                return createErrorClass(name.asString());
174            }
175    
176            @NotNull
177            @Override
178            @SuppressWarnings({"unchecked"}) // KT-9898 Impossible implement kotlin interface in java
179            public Set getContributedVariables(@NotNull Name name, @NotNull LookupLocation location) {
180                return ERROR_PROPERTY_GROUP;
181            }
182    
183            @Override
184            public PackageViewDescriptor getPackage(@NotNull Name name) {
185                return null;
186            }
187    
188            @NotNull
189            @Override
190            public Set<FunctionDescriptor> getContributedFunctions(@NotNull Name name, @NotNull LookupLocation location) {
191                return Collections.<FunctionDescriptor>singleton(createErrorFunction(this));
192            }
193    
194            @NotNull
195            @Override
196            public Collection<DeclarationDescriptor> getContributedDescriptors(
197                    @NotNull DescriptorKindFilter kindFilter, @NotNull Function1<? super Name, ? extends Boolean> nameFilter
198            ) {
199                return Collections.emptyList();
200            }
201    
202            @Override
203            public String toString() {
204                return "ErrorScope{" + debugMessage + '}';
205            }
206    
207            @Override
208            public void printScopeStructure(@NotNull Printer p) {
209                p.println(getClass().getSimpleName(), ": ", debugMessage);
210            }
211        }
212    
213        private static class ThrowingScope implements MemberScope {
214            private final String debugMessage;
215    
216            private ThrowingScope(@NotNull String message) {
217                debugMessage = message;
218            }
219    
220            @Nullable
221            @Override
222            public ClassifierDescriptor getContributedClassifier(@NotNull Name name, @NotNull LookupLocation location) {
223                throw new IllegalStateException();
224            }
225    
226            @Nullable
227            @Override
228            public PackageViewDescriptor getPackage(@NotNull Name name) {
229                throw new IllegalStateException();
230            }
231    
232            @NotNull
233            @Override
234            @SuppressWarnings({"unchecked"}) // KT-9898 Impossible implement kotlin interface from java
235            public Collection getContributedVariables(@NotNull Name name, @NotNull LookupLocation location) {
236                throw new IllegalStateException();
237            }
238    
239            @NotNull
240            @Override
241            public Collection<FunctionDescriptor> getContributedFunctions(@NotNull Name name, @NotNull LookupLocation location) {
242                throw new IllegalStateException();
243            }
244    
245            @NotNull
246            @Override
247            public Collection<DeclarationDescriptor> getContributedDescriptors(
248                    @NotNull DescriptorKindFilter kindFilter, @NotNull Function1<? super Name, ? extends Boolean> nameFilter
249            ) {
250                throw new IllegalStateException();
251            }
252    
253            @Override
254            public String toString() {
255                return "ThrowingScope{" + debugMessage + '}';
256            }
257    
258            @Override
259            public void printScopeStructure(@NotNull Printer p) {
260                p.println(getClass().getSimpleName(), ": ", debugMessage);
261            }
262        }
263    
264        private static final ErrorClassDescriptor ERROR_CLASS = new ErrorClassDescriptor(null);
265    
266        private static class ErrorClassDescriptor extends ClassDescriptorImpl {
267            public ErrorClassDescriptor(@Nullable String name) {
268                super(getErrorModule(), Name.special(name == null ? "<ERROR CLASS>" : "<ERROR CLASS: " + name + ">"),
269                      Modality.OPEN, Collections.<KotlinType>emptyList(), SourceElement.NO_SOURCE);
270    
271                ConstructorDescriptorImpl errorConstructor = ConstructorDescriptorImpl.create(this, Annotations.Companion.getEMPTY(), true, SourceElement.NO_SOURCE);
272                errorConstructor.initialize(Collections.<ValueParameterDescriptor>emptyList(),
273                                            Visibilities.INTERNAL);
274                MemberScope memberScope = createErrorScope(getName().asString());
275                errorConstructor.setReturnType(
276                        new ErrorTypeImpl(
277                                createErrorTypeConstructorWithCustomDebugName("<ERROR>", this),
278                                memberScope
279                        )
280                );
281    
282                initialize(memberScope, Collections.<ConstructorDescriptor>singleton(errorConstructor), errorConstructor);
283            }
284    
285            @NotNull
286            @Override
287            public ClassDescriptor substitute(@NotNull TypeSubstitutor substitutor) {
288                return this;
289            }
290    
291            @Override
292            public String toString() {
293                return getName().asString();
294            }
295    
296            @NotNull
297            @Override
298            public MemberScope getMemberScope(@NotNull List<? extends TypeProjection> typeArguments) {
299                return createErrorScope("Error scope for class " + getName() + " with arguments: " + typeArguments);
300            }
301    
302            @NotNull
303            @Override
304            public MemberScope getMemberScope(@NotNull TypeSubstitution typeSubstitution) {
305                return createErrorScope("Error scope for class " + getName() + " with arguments: " + typeSubstitution);
306            }
307        }
308    
309        @NotNull
310        public static ClassDescriptor createErrorClass(@NotNull String debugMessage) {
311            return new ErrorClassDescriptor(debugMessage);
312        }
313    
314        @NotNull
315        public static MemberScope createErrorScope(@NotNull String debugMessage) {
316            return createErrorScope(debugMessage, false);
317        }
318    
319        @NotNull
320        public static MemberScope createErrorScope(@NotNull String debugMessage, boolean throwExceptions) {
321            if (throwExceptions) {
322                return new ThrowingScope(debugMessage);
323            }
324            return new ErrorScope(debugMessage);
325        }
326    
327        private static final KotlinType ERROR_PROPERTY_TYPE = createErrorType("<ERROR PROPERTY TYPE>");
328        private static final PropertyDescriptor ERROR_PROPERTY = createErrorProperty();
329    
330        private static final Set<PropertyDescriptor> ERROR_PROPERTY_GROUP = Collections.singleton(ERROR_PROPERTY);
331    
332        @NotNull
333        private static PropertyDescriptorImpl createErrorProperty() {
334            PropertyDescriptorImpl descriptor = PropertyDescriptorImpl.create(
335                    ERROR_CLASS,
336                    Annotations.Companion.getEMPTY(),
337                    Modality.OPEN,
338                    Visibilities.INTERNAL,
339                    true,
340                    Name.special("<ERROR PROPERTY>"),
341                    CallableMemberDescriptor.Kind.DECLARATION,
342                    SourceElement.NO_SOURCE,
343                    /* lateInit = */ false,
344                    /* isConst = */ false
345            );
346            descriptor.setType(ERROR_PROPERTY_TYPE,
347                               Collections.<TypeParameterDescriptor>emptyList(),
348                               null,
349                               (KotlinType) null
350            );
351    
352            return descriptor;
353        }
354    
355        @NotNull
356        private static SimpleFunctionDescriptor createErrorFunction(@NotNull ErrorScope ownerScope) {
357            ErrorSimpleFunctionDescriptorImpl function = new ErrorSimpleFunctionDescriptorImpl(ERROR_CLASS, ownerScope);
358            function.initialize(
359                    null,
360                    null,
361                    Collections.<TypeParameterDescriptorImpl>emptyList(), // TODO
362                    Collections.<ValueParameterDescriptor>emptyList(), // TODO
363                    createErrorType("<ERROR FUNCTION RETURN TYPE>"),
364                    Modality.OPEN,
365                    Visibilities.INTERNAL
366            );
367            return function;
368        }
369    
370        @NotNull
371        public static KotlinType createErrorType(@NotNull String debugMessage) {
372            return createErrorTypeWithArguments(debugMessage, Collections.<TypeProjection>emptyList());
373        }
374    
375        @NotNull
376        public static KotlinType createErrorTypeWithCustomDebugName(@NotNull String debugName) {
377            return createErrorTypeWithCustomConstructor(debugName, createErrorTypeConstructorWithCustomDebugName(debugName));
378        }
379    
380        @NotNull
381        public static KotlinType createErrorTypeWithCustomConstructor(@NotNull String debugName, @NotNull TypeConstructor typeConstructor) {
382            return new ErrorTypeImpl(typeConstructor, createErrorScope(debugName));
383        }
384    
385        @NotNull
386        public static KotlinType createErrorTypeWithArguments(@NotNull String debugMessage, @NotNull List<TypeProjection> arguments) {
387            return new ErrorTypeImpl(createErrorTypeConstructor(debugMessage), createErrorScope(debugMessage), arguments);
388        }
389    
390        @NotNull
391        public static TypeConstructor createErrorTypeConstructor(@NotNull String debugMessage) {
392            return createErrorTypeConstructorWithCustomDebugName("[ERROR : " + debugMessage + "]", ERROR_CLASS);
393        }
394    
395        @NotNull
396        public static TypeConstructor createErrorTypeConstructorWithCustomDebugName(@NotNull String debugName) {
397            return createErrorTypeConstructorWithCustomDebugName(debugName, ERROR_CLASS);
398        }
399    
400        @NotNull
401        private static TypeConstructor createErrorTypeConstructorWithCustomDebugName(
402                @NotNull final String debugName, @NotNull final ErrorClassDescriptor errorClass
403        ) {
404            return new TypeConstructor() {
405                @NotNull
406                @Override
407                public List<TypeParameterDescriptor> getParameters() {
408                    return emptyList();
409                }
410    
411                @NotNull
412                @Override
413                public Collection<KotlinType> getSupertypes() {
414                    return emptyList();
415                }
416    
417                @Override
418                public boolean isFinal() {
419                    return false;
420                }
421    
422                @Override
423                public boolean isDenotable() {
424                    return false;
425                }
426    
427                @Nullable
428                @Override
429                public ClassifierDescriptor getDeclarationDescriptor() {
430                    return errorClass;
431                }
432    
433                @NotNull
434                @Override
435                public KotlinBuiltIns getBuiltIns() {
436                    return DefaultBuiltIns.getInstance();
437                }
438    
439                @NotNull
440                @Override
441                public Annotations getAnnotations() {
442                    return Annotations.Companion.getEMPTY();
443                }
444    
445                @Override
446                public String toString() {
447                    return debugName;
448                }
449            };
450        }
451    
452        public static boolean containsErrorType(@Nullable KotlinType type) {
453            if (type == null) return false;
454            if (type.isError()) return true;
455            for (TypeProjection projection : type.getArguments()) {
456                if (!projection.isStarProjection() && containsErrorType(projection.getType())) return true;
457            }
458            return false;
459        }
460    
461        public static boolean isError(@NotNull DeclarationDescriptor candidate) {
462            return isErrorClass(candidate) || isErrorClass(candidate.getContainingDeclaration()) || candidate == ERROR_MODULE;
463        }
464    
465        private static boolean isErrorClass(@Nullable DeclarationDescriptor candidate) {
466            return candidate instanceof ErrorClassDescriptor;
467        }
468    
469        @NotNull
470        public static TypeParameterDescriptor createErrorTypeParameter(int index, @NotNull String debugMessage) {
471            return TypeParameterDescriptorImpl.createWithDefaultBound(
472                    ERROR_CLASS,
473                    Annotations.Companion.getEMPTY(),
474                    false,
475                    Variance.INVARIANT,
476                    Name.special("<ERROR: " + debugMessage + ">"),
477                    index
478            );
479        }
480    
481        private static class ErrorTypeImpl implements KotlinType {
482            private final TypeConstructor constructor;
483            private final MemberScope memberScope;
484            private final List<TypeProjection> arguments;
485    
486            private ErrorTypeImpl(
487                    @NotNull TypeConstructor constructor,
488                    @NotNull MemberScope memberScope,
489                    @NotNull List<TypeProjection> arguments
490            ) {
491                this.constructor = constructor;
492                this.memberScope = memberScope;
493                this.arguments = arguments;
494            }
495    
496            private ErrorTypeImpl(@NotNull TypeConstructor constructor, @NotNull MemberScope memberScope) {
497                this(constructor, memberScope, Collections.<TypeProjection>emptyList());
498            }
499    
500            @NotNull
501            @Override
502            public TypeConstructor getConstructor() {
503                return constructor;
504            }
505    
506            @NotNull
507            @Override
508            public List<TypeProjection> getArguments() {
509                return arguments;
510            }
511    
512            @NotNull
513            @Override
514            public TypeSubstitution getSubstitution() {
515                return TypeConstructorSubstitution.create(constructor, arguments);
516            }
517    
518            @Override
519            public boolean isMarkedNullable() {
520                return false;
521            }
522    
523            @NotNull
524            @Override
525            public MemberScope getMemberScope() {
526                return memberScope;
527            }
528    
529            @Override
530            public boolean isError() {
531                return true;
532            }
533    
534            @NotNull
535            @Override
536            public Annotations getAnnotations() {
537                return Annotations.Companion.getEMPTY();
538            }
539    
540            @Nullable
541            @Override
542            public <T extends TypeCapability> T getCapability(@NotNull Class<T> capabilityClass) {
543                return null;
544            }
545    
546            @NotNull
547            @Override
548            public TypeCapabilities getCapabilities() {
549                return TypeCapabilities.NONE.INSTANCE;
550            }
551    
552            @Override
553            public String toString() {
554                return constructor.toString() + (arguments.isEmpty() ? "" : joinToString(arguments, ", ", "<", ">", -1, "...", null));
555            }
556        }
557    
558        @NotNull
559        public static ModuleDescriptor getErrorModule() {
560            return ERROR_MODULE;
561        }
562    
563        public static boolean isUninferredParameter(@Nullable KotlinType type) {
564            return type != null && type.getConstructor() instanceof UninferredParameterTypeConstructor;
565        }
566    
567        public static boolean containsUninferredParameter(@Nullable KotlinType type) {
568            return TypeUtils.containsSpecialType(type, new Function1<KotlinType, Boolean>() {
569                @Override
570                public Boolean invoke(KotlinType argumentType) {
571                    return isUninferredParameter(argumentType);
572                }
573            });
574        }
575    
576        @NotNull
577        public static KotlinType createUninferredParameterType(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
578            return createErrorTypeWithCustomConstructor("Scope for error type for not inferred parameter: " + typeParameterDescriptor.getName(),
579                                                        new UninferredParameterTypeConstructor(typeParameterDescriptor));
580        }
581    
582        public static class UninferredParameterTypeConstructor implements TypeConstructor {
583            private final TypeParameterDescriptor typeParameterDescriptor;
584            private final TypeConstructor errorTypeConstructor;
585    
586            private UninferredParameterTypeConstructor(@NotNull TypeParameterDescriptor descriptor) {
587                typeParameterDescriptor = descriptor;
588                errorTypeConstructor = createErrorTypeConstructorWithCustomDebugName("CANT_INFER_TYPE_PARAMETER: " + descriptor.getName());
589            }
590    
591            @NotNull
592            public TypeParameterDescriptor getTypeParameterDescriptor() {
593                return typeParameterDescriptor;
594            }
595    
596            @NotNull
597            @Override
598            public List<TypeParameterDescriptor> getParameters() {
599                return errorTypeConstructor.getParameters();
600            }
601    
602            @NotNull
603            @Override
604            public Collection<KotlinType> getSupertypes() {
605                return errorTypeConstructor.getSupertypes();
606            }
607    
608            @Override
609            public boolean isFinal() {
610                return errorTypeConstructor.isFinal();
611            }
612    
613            @Override
614            public boolean isDenotable() {
615                return errorTypeConstructor.isDenotable();
616            }
617    
618            @Nullable
619            @Override
620            public ClassifierDescriptor getDeclarationDescriptor() {
621                return errorTypeConstructor.getDeclarationDescriptor();
622            }
623    
624            @NotNull
625            @Override
626            public Annotations getAnnotations() {
627                return errorTypeConstructor.getAnnotations();
628            }
629    
630            @NotNull
631            @Override
632            public KotlinBuiltIns getBuiltIns() {
633                return DescriptorUtilsKt.getBuiltIns(typeParameterDescriptor);
634            }
635        }
636    
637        private ErrorUtils() {}
638    }