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