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