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.PropertyDescriptorImpl;
026    import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
027    import org.jetbrains.jet.lang.resolve.ImportPath;
028    import org.jetbrains.jet.lang.resolve.name.LabelName;
029    import org.jetbrains.jet.lang.resolve.name.Name;
030    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
031    import org.jetbrains.jet.lang.types.error.ErrorClassDescriptor;
032    import org.jetbrains.jet.lang.types.error.ErrorSimpleFunctionDescriptorImpl;
033    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
034    import org.jetbrains.jet.utils.Printer;
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            @Override
160            public void printScopeStructure(@NotNull Printer p) {
161                p.println(getClass().getSimpleName(), ": ", debugMessage);
162            }
163        }
164    
165        private static class ThrowingScope implements JetScope {
166            private final String debugMessage;
167    
168            private ThrowingScope(@NotNull String message) {
169                debugMessage = message;
170            }
171    
172            @Nullable
173            @Override
174            public ClassifierDescriptor getClassifier(@NotNull Name name) {
175                throw new IllegalStateException();
176            }
177    
178            @Nullable
179            @Override
180            public ClassDescriptor getObjectDescriptor(@NotNull Name name) {
181                throw new IllegalStateException();
182            }
183    
184            @NotNull
185            @Override
186            public Collection<ClassDescriptor> getObjectDescriptors() {
187                throw new IllegalStateException();
188            }
189    
190            @Nullable
191            @Override
192            public NamespaceDescriptor getNamespace(@NotNull Name name) {
193                throw new IllegalStateException();
194            }
195    
196            @NotNull
197            @Override
198            public Collection<VariableDescriptor> getProperties(@NotNull Name name) {
199                throw new IllegalStateException();
200            }
201    
202            @Nullable
203            @Override
204            public VariableDescriptor getLocalVariable(@NotNull Name name) {
205                throw new IllegalStateException();
206            }
207    
208            @NotNull
209            @Override
210            public Collection<FunctionDescriptor> getFunctions(@NotNull Name name) {
211                throw new IllegalStateException();
212            }
213    
214            @NotNull
215            @Override
216            public DeclarationDescriptor getContainingDeclaration() {
217                return ERROR_MODULE;
218            }
219    
220            @NotNull
221            @Override
222            public Collection<DeclarationDescriptor> getDeclarationsByLabel(@NotNull LabelName labelName) {
223                throw new IllegalStateException();
224            }
225    
226            @NotNull
227            @Override
228            public Collection<DeclarationDescriptor> getAllDescriptors() {
229                throw new IllegalStateException();
230            }
231    
232            @NotNull
233            @Override
234            public List<ReceiverParameterDescriptor> getImplicitReceiversHierarchy() {
235                throw new IllegalStateException();
236            }
237    
238            @NotNull
239            @Override
240            public Collection<DeclarationDescriptor> getOwnDeclaredDescriptors() {
241                throw new IllegalStateException();
242            }
243    
244            @Override
245            public String toString() {
246                return "ThrowingScope{" + debugMessage + '}';
247            }
248    
249            @Override
250            public void printScopeStructure(@NotNull Printer p) {
251                p.println(getClass().getSimpleName(), ": ", debugMessage);
252            }
253        }
254    
255        private static final ErrorClassDescriptor ERROR_CLASS = new ErrorClassDescriptor("");
256    
257        @NotNull
258        public static JetScope createErrorScope(@NotNull String debugMessage) {
259            return createErrorScope(debugMessage, false);
260        }
261    
262        @NotNull
263        public static JetScope createErrorScope(@NotNull String debugMessage, boolean throwExceptions) {
264            if (throwExceptions) {
265                return new ThrowingScope(debugMessage);
266            }
267            return new ErrorScope(debugMessage);
268        }
269    
270        private static final JetType ERROR_PROPERTY_TYPE = createErrorType("<ERROR PROPERTY TYPE>");
271        private static final VariableDescriptor ERROR_PROPERTY = new PropertyDescriptorImpl(
272                ERROR_CLASS,
273                Collections.<AnnotationDescriptor>emptyList(),
274                Modality.OPEN,
275                Visibilities.INTERNAL,
276                true,
277                null,
278                ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER,
279                Name.special("<ERROR PROPERTY>"),
280                ERROR_PROPERTY_TYPE,
281                CallableMemberDescriptor.Kind.DECLARATION);
282        private static final Set<VariableDescriptor> ERROR_PROPERTY_GROUP = Collections.singleton(ERROR_PROPERTY);
283    
284        @NotNull
285        private static SimpleFunctionDescriptor createErrorFunction(@NotNull ErrorScope ownerScope) {
286            ErrorSimpleFunctionDescriptorImpl function = new ErrorSimpleFunctionDescriptorImpl(ownerScope);
287            function.initialize(
288                    null,
289                    ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER,
290                    Collections.<TypeParameterDescriptorImpl>emptyList(), // TODO
291                    Collections.<ValueParameterDescriptor>emptyList(), // TODO
292                    createErrorType("<ERROR FUNCTION RETURN TYPE>"),
293                    Modality.OPEN,
294                    Visibilities.INTERNAL,
295                    /*isInline = */ false
296            );
297            return function;
298        }
299    
300        @NotNull
301        public static JetType createErrorType(@NotNull String debugMessage) {
302            return new ErrorTypeImpl(createErrorTypeConstructor(debugMessage), createErrorScope(debugMessage));
303        }
304    
305        @NotNull
306        public static JetType createErrorTypeWithCustomDebugName(@NotNull String debugName) {
307            return new ErrorTypeImpl(createErrorTypeConstructorWithCustomDebugName(debugName), createErrorScope(debugName));
308        }
309    
310        @NotNull
311        public static TypeConstructor createErrorTypeConstructor(@NotNull String debugMessage) {
312            return createErrorTypeConstructorWithCustomDebugName("[ERROR : " + debugMessage + "]");
313        }
314    
315        @NotNull
316        private static TypeConstructor createErrorTypeConstructorWithCustomDebugName(@NotNull String debugName) {
317            return new TypeConstructorImpl(ERROR_CLASS, Collections.<AnnotationDescriptor>emptyList(), false, debugName,
318                                    Collections.<TypeParameterDescriptorImpl>emptyList(),
319                                    Collections.singleton(KotlinBuiltIns.getInstance().getAnyType()));
320        }
321    
322        @NotNull
323        public static ClassDescriptor getErrorClass() {
324            return ERROR_CLASS;
325        }
326    
327        public static boolean containsErrorType(@Nullable JetType type) {
328            if (type == null) return false;
329            if (type instanceof NamespaceType) return false;
330            if (type.isError()) return true;
331            for (TypeProjection projection : type.getArguments()) {
332                if (containsErrorType(projection.getType())) return true;
333            }
334            return false;
335        }
336    
337        public static boolean isError(@NotNull DeclarationDescriptor candidate) {
338            return isErrorClass(candidate) || isErrorClass(candidate.getContainingDeclaration()) || candidate == ERROR_MODULE;
339        }
340    
341        private static boolean isErrorClass(@Nullable DeclarationDescriptor candidate) {
342            return candidate instanceof ErrorClassDescriptor;
343        }
344    
345        private static class ErrorTypeImpl implements JetType {
346            private final TypeConstructor constructor;
347            private final JetScope memberScope;
348    
349            private ErrorTypeImpl(@NotNull TypeConstructor constructor, @NotNull JetScope memberScope) {
350                this.constructor = constructor;
351                this.memberScope = memberScope;
352            }
353    
354            @NotNull
355            @Override
356            public TypeConstructor getConstructor() {
357                return constructor;
358            }
359    
360            @NotNull
361            @Override
362            public List<TypeProjection> getArguments() {
363                return Collections.emptyList();
364            }
365    
366            @Override
367            public boolean isNullable() {
368                return false;
369            }
370    
371            @NotNull
372            @Override
373            public JetScope getMemberScope() {
374                return memberScope;
375            }
376    
377            @Override
378            public boolean isError() {
379                return true;
380            }
381    
382            @NotNull
383            @Override
384            public List<AnnotationDescriptor> getAnnotations() {
385                return Collections.emptyList();
386            }
387    
388            @Override
389            public String toString() {
390                return constructor.toString();
391            }
392        }
393    
394        @NotNull
395        public static ModuleDescriptor getErrorModule() {
396            return ERROR_MODULE;
397        }
398    
399        private ErrorUtils() {}
400    }