001    /*
002     * Copyright 2010-2013 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.jet.lang.types;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.jet.lang.ModuleConfiguration;
022    import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
023    import org.jetbrains.jet.lang.descriptors.*;
024    import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
025    import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl;
026    import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl;
027    import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
028    import org.jetbrains.jet.lang.resolve.ImportPath;
029    import org.jetbrains.jet.lang.resolve.name.LabelName;
030    import org.jetbrains.jet.lang.resolve.name.Name;
031    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
032    import org.jetbrains.jet.lang.types.error.ErrorClassDescriptor;
033    import org.jetbrains.jet.lang.types.error.ErrorSimpleFunctionDescriptorImpl;
034    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
035    
036    import java.util.Collection;
037    import java.util.Collections;
038    import java.util.List;
039    import java.util.Set;
040    
041    public class ErrorUtils {
042    
043        private static final ModuleDescriptor ERROR_MODULE;
044        static {
045            ModuleDescriptorImpl module = new ModuleDescriptorImpl(
046                    Name.special("<ERROR MODULE>"),
047                    Collections.<ImportPath>emptyList(),
048                    PlatformToKotlinClassMap.EMPTY
049            );
050            module.setModuleConfiguration(ModuleConfiguration.EMPTY);
051            ERROR_MODULE = module;
052        }
053    
054        public static boolean containsErrorType(@NotNull FunctionDescriptor function) {
055            if (containsErrorType(function.getReturnType())) {
056                return true;
057            }
058            ReceiverParameterDescriptor receiverParameter = function.getReceiverParameter();
059            if (receiverParameter != null && containsErrorType(receiverParameter.getType())) {
060                return true;
061            }
062            for (ValueParameterDescriptor parameter : function.getValueParameters()) {
063                if (containsErrorType(parameter.getType())) {
064                    return true;
065                }
066            }
067            for (TypeParameterDescriptor parameter : function.getTypeParameters()) {
068                for (JetType upperBound : parameter.getUpperBounds()) {
069                    if (containsErrorType(upperBound)) {
070                        return true;
071                    }
072                }
073            }
074    
075            return false;
076        }
077    
078    
079        public static class ErrorScope implements JetScope {
080            private final String debugMessage;
081    
082            private ErrorScope(@NotNull String debugMessage) {
083                this.debugMessage = debugMessage;
084            }
085    
086            @Override
087            public ClassifierDescriptor getClassifier(@NotNull Name name) {
088                return ERROR_CLASS;
089            }
090    
091            @Override
092            public ClassDescriptor getObjectDescriptor(@NotNull Name name) {
093                return ERROR_CLASS;
094            }
095    
096            @NotNull
097            @Override
098            public Set<ClassDescriptor> getObjectDescriptors() {
099                return Collections.emptySet();
100            }
101    
102            @NotNull
103            @Override
104            public Set<VariableDescriptor> getProperties(@NotNull Name name) {
105                return ERROR_PROPERTY_GROUP;
106            }
107    
108            @Override
109            public VariableDescriptor getLocalVariable(@NotNull Name name) {
110                return ERROR_PROPERTY;
111            }
112    
113            @Override
114            public NamespaceDescriptor getNamespace(@NotNull Name name) {
115                return null; // TODO : review
116            }
117    
118            @NotNull
119            @Override
120            public List<ReceiverParameterDescriptor> getImplicitReceiversHierarchy() {
121                return Collections.emptyList();
122            }
123    
124            @NotNull
125            @Override
126            public Set<FunctionDescriptor> getFunctions(@NotNull Name name) {
127                return Collections.<FunctionDescriptor>singleton(createErrorFunction(this));
128            }
129    
130            @NotNull
131            @Override
132            public DeclarationDescriptor getContainingDeclaration() {
133                return ERROR_MODULE;
134            }
135    
136            @NotNull
137            @Override
138            public Collection<DeclarationDescriptor> getDeclarationsByLabel(@NotNull LabelName labelName) {
139                return Collections.emptyList();
140            }
141    
142            @NotNull
143            @Override
144            public Collection<DeclarationDescriptor> getAllDescriptors() {
145                return Collections.emptyList();
146            }
147    
148            @NotNull
149            @Override
150            public Collection<DeclarationDescriptor> getOwnDeclaredDescriptors() {
151                return Collections.emptyList();
152            }
153    
154            @Override
155            public String toString() {
156                return "ErrorScope{" + debugMessage + '}';
157            }
158        }
159    
160        private static class ThrowingScope implements JetScope {
161            private final String debugMessage;
162    
163            private ThrowingScope(@NotNull String message) {
164                debugMessage = message;
165            }
166    
167            @Nullable
168            @Override
169            public ClassifierDescriptor getClassifier(@NotNull Name name) {
170                throw new IllegalStateException();
171            }
172    
173            @Nullable
174            @Override
175            public ClassDescriptor getObjectDescriptor(@NotNull Name name) {
176                throw new IllegalStateException();
177            }
178    
179            @NotNull
180            @Override
181            public Collection<ClassDescriptor> getObjectDescriptors() {
182                throw new IllegalStateException();
183            }
184    
185            @Nullable
186            @Override
187            public NamespaceDescriptor getNamespace(@NotNull Name name) {
188                throw new IllegalStateException();
189            }
190    
191            @NotNull
192            @Override
193            public Collection<VariableDescriptor> getProperties(@NotNull Name name) {
194                throw new IllegalStateException();
195            }
196    
197            @Nullable
198            @Override
199            public VariableDescriptor getLocalVariable(@NotNull Name name) {
200                throw new IllegalStateException();
201            }
202    
203            @NotNull
204            @Override
205            public Collection<FunctionDescriptor> getFunctions(@NotNull Name name) {
206                throw new IllegalStateException();
207            }
208    
209            @NotNull
210            @Override
211            public DeclarationDescriptor getContainingDeclaration() {
212                return ERROR_MODULE;
213            }
214    
215            @NotNull
216            @Override
217            public Collection<DeclarationDescriptor> getDeclarationsByLabel(@NotNull LabelName labelName) {
218                throw new IllegalStateException();
219            }
220    
221            @NotNull
222            @Override
223            public Collection<DeclarationDescriptor> getAllDescriptors() {
224                throw new IllegalStateException();
225            }
226    
227            @NotNull
228            @Override
229            public List<ReceiverParameterDescriptor> getImplicitReceiversHierarchy() {
230                throw new IllegalStateException();
231            }
232    
233            @NotNull
234            @Override
235            public Collection<DeclarationDescriptor> getOwnDeclaredDescriptors() {
236                throw new IllegalStateException();
237            }
238    
239            @Override
240            public String toString() {
241                return "ThrowingScope{" + debugMessage + '}';
242            }
243        }
244    
245        private static final ErrorClassDescriptor ERROR_CLASS = new ErrorClassDescriptor("");
246    
247        private static final Set<ConstructorDescriptor> ERROR_CONSTRUCTOR_GROUP = Collections.singleton(createErrorConstructor());
248    
249        private static final ConstructorDescriptor ERROR_CONSTRUCTOR = new ConstructorDescriptorImpl(ERROR_CLASS, Collections.<AnnotationDescriptor>emptyList(), true);
250    
251        static {
252            ERROR_CLASS.initializeErrorClass();
253        }
254    
255        @NotNull
256        public static Set<ConstructorDescriptor> getErrorConstructorGroup() {
257            return ERROR_CONSTRUCTOR_GROUP;
258        }
259    
260        @NotNull
261        public static ConstructorDescriptor getErrorConstructor() {
262            return ERROR_CONSTRUCTOR;
263        }
264    
265        @NotNull
266        public static JetScope createErrorScope(@NotNull String debugMessage) {
267            return createErrorScope(debugMessage, false);
268        }
269    
270        @NotNull
271        public static JetScope createErrorScope(@NotNull String debugMessage, boolean throwExceptions) {
272            if (throwExceptions) {
273                return new ThrowingScope(debugMessage);
274            }
275            return new ErrorScope(debugMessage);
276        }
277    
278        private static final JetType ERROR_PROPERTY_TYPE = createErrorType("<ERROR PROPERTY TYPE>");
279        private static final VariableDescriptor ERROR_PROPERTY = new PropertyDescriptorImpl(
280                ERROR_CLASS,
281                Collections.<AnnotationDescriptor>emptyList(),
282                Modality.OPEN,
283                Visibilities.INTERNAL,
284                true,
285                null,
286                ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER,
287                Name.special("<ERROR PROPERTY>"),
288                ERROR_PROPERTY_TYPE,
289                CallableMemberDescriptor.Kind.DECLARATION);
290        private static final Set<VariableDescriptor> ERROR_PROPERTY_GROUP = Collections.singleton(ERROR_PROPERTY);
291    
292        @NotNull
293        private static SimpleFunctionDescriptor createErrorFunction(@NotNull ErrorScope ownerScope) {
294            ErrorSimpleFunctionDescriptorImpl function = new ErrorSimpleFunctionDescriptorImpl(ownerScope);
295            function.initialize(
296                    null,
297                    ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER,
298                    Collections.<TypeParameterDescriptorImpl>emptyList(), // TODO
299                    Collections.<ValueParameterDescriptor>emptyList(), // TODO
300                    createErrorType("<ERROR FUNCTION RETURN TYPE>"),
301                    Modality.OPEN,
302                    Visibilities.INTERNAL,
303                    /*isInline = */ false
304            );
305            return function;
306        }
307    
308        @NotNull
309        private static ConstructorDescriptor createErrorConstructor() {
310            ConstructorDescriptorImpl r = new ConstructorDescriptorImpl(ERROR_CLASS, Collections.<AnnotationDescriptor>emptyList(), false);
311            r.initialize(
312                    Collections.<TypeParameterDescriptor>emptyList(), // TODO
313                    Collections.<ValueParameterDescriptor>emptyList(), // TODO
314                    Visibilities.INTERNAL
315            );
316            r.setReturnType(createErrorType("<ERROR RETURN TYPE>"));
317            return r;
318        }
319    
320        @NotNull
321        public static JetType createErrorType(@NotNull String debugMessage) {
322            return new ErrorTypeImpl(createErrorTypeConstructor(debugMessage), createErrorScope(debugMessage));
323        }
324    
325        @NotNull
326        public static JetType createErrorTypeWithCustomDebugName(@NotNull String debugName) {
327            return new ErrorTypeImpl(createErrorTypeConstructorWithCustomDebugName(debugName), createErrorScope(debugName));
328        }
329    
330        @NotNull
331        public static TypeConstructor createErrorTypeConstructor(@NotNull String debugMessage) {
332            return createErrorTypeConstructorWithCustomDebugName("[ERROR : " + debugMessage + "]");
333        }
334    
335        @NotNull
336        private static TypeConstructor createErrorTypeConstructorWithCustomDebugName(@NotNull String debugName) {
337            return new TypeConstructorImpl(ERROR_CLASS, Collections.<AnnotationDescriptor>emptyList(), false, debugName,
338                                    Collections.<TypeParameterDescriptorImpl>emptyList(),
339                                    Collections.singleton(KotlinBuiltIns.getInstance().getAnyType()));
340        }
341    
342        @NotNull
343        public static ClassDescriptor getErrorClass() {
344            return ERROR_CLASS;
345        }
346    
347        public static boolean containsErrorType(@Nullable JetType type) {
348            if (type == null) return false;
349            if (type instanceof NamespaceType) return false;
350            if (type.isError()) return true;
351            for (TypeProjection projection : type.getArguments()) {
352                if (containsErrorType(projection.getType())) return true;
353            }
354            return false;
355        }
356    
357        public static boolean isError(@NotNull DeclarationDescriptor candidate) {
358            return isErrorClass(candidate) || isErrorClass(candidate.getContainingDeclaration()) || candidate == ERROR_MODULE;
359        }
360    
361        private static boolean isErrorClass(@Nullable DeclarationDescriptor candidate) {
362            return candidate instanceof ErrorClassDescriptor;
363        }
364    
365        @NotNull
366        public static ErrorClassDescriptor createErrorClass(@NotNull String debugMessage) {
367            ErrorClassDescriptor result = new ErrorClassDescriptor(debugMessage);
368            result.initializeErrorClass();
369            return result;
370        }
371    
372        private static class ErrorTypeImpl implements JetType {
373            private final TypeConstructor constructor;
374            private final JetScope memberScope;
375    
376            private ErrorTypeImpl(@NotNull TypeConstructor constructor, @NotNull JetScope memberScope) {
377                this.constructor = constructor;
378                this.memberScope = memberScope;
379            }
380    
381            @NotNull
382            @Override
383            public TypeConstructor getConstructor() {
384                return constructor;
385            }
386    
387            @NotNull
388            @Override
389            public List<TypeProjection> getArguments() {
390                return Collections.emptyList();
391            }
392    
393            @Override
394            public boolean isNullable() {
395                return false;
396            }
397    
398            @NotNull
399            @Override
400            public JetScope getMemberScope() {
401                return memberScope;
402            }
403    
404            @Override
405            public boolean isError() {
406                return true;
407            }
408    
409            @Override
410            public List<AnnotationDescriptor> getAnnotations() {
411                return Collections.emptyList();
412            }
413    
414            @Override
415            public String toString() {
416                return constructor.toString();
417            }
418        }
419    
420        @NotNull
421        public static ModuleDescriptor getErrorModule() {
422            return ERROR_MODULE;
423        }
424    
425        private ErrorUtils() {}
426    }