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.resolve;
018    
019    import kotlin.CollectionsKt;
020    import kotlin.Unit;
021    import kotlin.jvm.functions.Function1;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.kotlin.descriptors.*;
025    import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl;
026    import org.jetbrains.kotlin.descriptors.impl.PropertyAccessorDescriptorImpl;
027    import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl;
028    import org.jetbrains.kotlin.name.Name;
029    import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
030    import org.jetbrains.kotlin.types.KotlinType;
031    import org.jetbrains.kotlin.types.TypeConstructor;
032    import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
033    
034    import java.util.*;
035    
036    import static org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.*;
037    
038    public class OverridingUtil {
039    
040        private static final List<ExternalOverridabilityCondition> EXTERNAL_CONDITIONS =
041                CollectionsKt.toList(ServiceLoader.load(
042                        ExternalOverridabilityCondition.class,
043                        ExternalOverridabilityCondition.class.getClassLoader()
044                ));
045    
046        public static final OverridingUtil DEFAULT = new OverridingUtil(new KotlinTypeChecker.TypeConstructorEquality() {
047            @Override
048            public boolean equals(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
049                return a.equals(b);
050            }
051        });
052    
053        @NotNull
054        public static OverridingUtil createWithEqualityAxioms(@NotNull KotlinTypeChecker.TypeConstructorEquality equalityAxioms) {
055            return new OverridingUtil(equalityAxioms);
056        }
057    
058        private final KotlinTypeChecker.TypeConstructorEquality equalityAxioms;
059    
060        private OverridingUtil(KotlinTypeChecker.TypeConstructorEquality axioms) {
061            equalityAxioms = axioms;
062        }
063    
064        @NotNull
065        public OverrideCompatibilityInfo isOverridableBy(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
066            return isOverridableBy(superDescriptor, subDescriptor, false);
067        }
068    
069        @NotNull
070        public OverrideCompatibilityInfo isOverridableByIncludingReturnType(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
071            return isOverridableBy(superDescriptor, subDescriptor, true);
072        }
073    
074        @NotNull
075        private OverrideCompatibilityInfo isOverridableBy(
076                @NotNull CallableDescriptor superDescriptor,
077                @NotNull CallableDescriptor subDescriptor,
078                boolean checkReturnType
079        ) {
080            if (superDescriptor instanceof FunctionDescriptor && !(subDescriptor instanceof FunctionDescriptor) ||
081                superDescriptor instanceof PropertyDescriptor && !(subDescriptor instanceof PropertyDescriptor)) {
082                return OverrideCompatibilityInfo.incompatible("Member kind mismatch");
083            }
084    
085            if (!(superDescriptor instanceof FunctionDescriptor) && !(superDescriptor instanceof PropertyDescriptor)) {
086                throw new IllegalArgumentException("This type of CallableDescriptor cannot be checked for overridability: " + superDescriptor);
087            }
088    
089            // TODO: check outside of this method
090            if (!superDescriptor.getName().equals(subDescriptor.getName())) {
091                return OverrideCompatibilityInfo.incompatible("Name mismatch");
092            }
093    
094            OverrideCompatibilityInfo receiverAndParameterResult = checkReceiverAndParameterCount(superDescriptor, subDescriptor);
095            if (receiverAndParameterResult != null) {
096                return receiverAndParameterResult;
097            }
098    
099            List<KotlinType> superValueParameters = compiledValueParameters(superDescriptor);
100            List<KotlinType> subValueParameters = compiledValueParameters(subDescriptor);
101    
102            List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
103            List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
104    
105            if (superTypeParameters.size() != subTypeParameters.size()) {
106                for (int i = 0; i < superValueParameters.size(); ++i) {
107                    // TODO: compare erasure
108                    if (!KotlinTypeChecker.DEFAULT.equalTypes(superValueParameters.get(i), subValueParameters.get(i))) {
109                        return OverrideCompatibilityInfo.incompatible("Type parameter number mismatch");
110                    }
111                }
112                return OverrideCompatibilityInfo.conflict("Type parameter number mismatch");
113            }
114    
115            KotlinTypeChecker typeChecker = createTypeChecker(superTypeParameters, subTypeParameters);
116    
117            for (int i = 0; i < superTypeParameters.size(); i++) {
118                if (!areTypeParametersEquivalent(superTypeParameters.get(i), subTypeParameters.get(i), typeChecker)) {
119                    return OverrideCompatibilityInfo.incompatible("Type parameter bounds mismatch");
120                }
121            }
122    
123            for (int i = 0; i < superValueParameters.size(); i++) {
124                if (!areTypesEquivalent(superValueParameters.get(i), subValueParameters.get(i), typeChecker)) {
125                    return OverrideCompatibilityInfo.incompatible("Value parameter type mismatch");
126                }
127            }
128    
129            if (checkReturnType) {
130                KotlinType superReturnType = superDescriptor.getReturnType();
131                KotlinType subReturnType = subDescriptor.getReturnType();
132    
133                if (superReturnType != null && subReturnType != null) {
134                    boolean bothErrors = subReturnType.isError() && superReturnType.isError();
135                    if (!bothErrors && !typeChecker.isSubtypeOf(subReturnType, superReturnType)) {
136                        return OverrideCompatibilityInfo.conflict("Return type mismatch");
137                    }
138                }
139            }
140    
141            for (ExternalOverridabilityCondition externalCondition : EXTERNAL_CONDITIONS) {
142                if (!externalCondition.isOverridable(superDescriptor, subDescriptor)) {
143                    return OverrideCompatibilityInfo.incompatible("External condition failed");
144                }
145            }
146    
147            return OverrideCompatibilityInfo.success();
148        }
149    
150        @NotNull
151        private KotlinTypeChecker createTypeChecker(
152                @NotNull List<TypeParameterDescriptor> firstParameters,
153                @NotNull List<TypeParameterDescriptor> secondParameters
154        ) {
155            assert firstParameters.size() == secondParameters.size() :
156                    "Should be the same number of type parameters: " + firstParameters + " vs " + secondParameters;
157            if (firstParameters.isEmpty()) return KotlinTypeChecker.withAxioms(equalityAxioms);
158    
159            final Map<TypeConstructor, TypeConstructor> matchingTypeConstructors = new HashMap<TypeConstructor, TypeConstructor>();
160            for (int i = 0; i < firstParameters.size(); i++) {
161                matchingTypeConstructors.put(firstParameters.get(i).getTypeConstructor(), secondParameters.get(i).getTypeConstructor());
162            }
163    
164            return KotlinTypeChecker.withAxioms(new KotlinTypeChecker.TypeConstructorEquality() {
165                @Override
166                public boolean equals(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
167                    if (equalityAxioms.equals(a, b)) return true;
168                    TypeConstructor img1 = matchingTypeConstructors.get(a);
169                    TypeConstructor img2 = matchingTypeConstructors.get(b);
170                    return (img1 != null && img1.equals(b)) || (img2 != null && img2.equals(a));
171                }
172            });
173        }
174    
175        @Nullable
176        static OverrideCompatibilityInfo checkReceiverAndParameterCount(
177                CallableDescriptor superDescriptor,
178                CallableDescriptor subDescriptor
179        ) {
180            if ((superDescriptor.getExtensionReceiverParameter() == null) != (subDescriptor.getExtensionReceiverParameter() == null)) {
181                return OverrideCompatibilityInfo.incompatible("Receiver presence mismatch");
182            }
183    
184            if (superDescriptor.getValueParameters().size() != subDescriptor.getValueParameters().size()) {
185                return OverrideCompatibilityInfo.incompatible("Value parameter number mismatch");
186            }
187    
188            return null;
189        }
190    
191        private static boolean areTypesEquivalent(
192                @NotNull KotlinType typeInSuper,
193                @NotNull KotlinType typeInSub,
194                @NotNull KotlinTypeChecker typeChecker
195        ) {
196            boolean bothErrors = typeInSuper.isError() && typeInSub.isError();
197            return bothErrors || typeChecker.equalTypes(typeInSuper, typeInSub);
198        }
199    
200        // See JLS 8, 8.4.4 Generic Methods
201        // TODO: use TypeSubstitutor instead
202        private static boolean areTypeParametersEquivalent(
203                @NotNull TypeParameterDescriptor superTypeParameter,
204                @NotNull TypeParameterDescriptor subTypeParameter,
205                @NotNull KotlinTypeChecker typeChecker
206        ) {
207            List<KotlinType> superBounds = superTypeParameter.getUpperBounds();
208            List<KotlinType> subBounds = new ArrayList<KotlinType>(subTypeParameter.getUpperBounds());
209            if (superBounds.size() != subBounds.size()) return false;
210    
211            outer:
212            for (KotlinType superBound : superBounds) {
213                ListIterator<KotlinType> it = subBounds.listIterator();
214                while (it.hasNext()) {
215                    KotlinType subBound = it.next();
216                    if (areTypesEquivalent(superBound, subBound, typeChecker)) {
217                        it.remove();
218                        continue outer;
219                    }
220                }
221                return false;
222            }
223    
224            return true;
225        }
226    
227        static List<KotlinType> compiledValueParameters(CallableDescriptor callableDescriptor) {
228            ReceiverParameterDescriptor receiverParameter = callableDescriptor.getExtensionReceiverParameter();
229            List<KotlinType> parameters = new ArrayList<KotlinType>();
230            if (receiverParameter != null) {
231                parameters.add(receiverParameter.getType());
232            }
233            for (ValueParameterDescriptor valueParameterDescriptor : callableDescriptor.getValueParameters()) {
234                parameters.add(valueParameterDescriptor.getType());
235            }
236            return parameters;
237        }
238    
239        public static void generateOverridesInFunctionGroup(
240                @SuppressWarnings("UnusedParameters")
241                @NotNull Name name, //DO NOT DELETE THIS PARAMETER: needed to make sure all descriptors have the same name
242                @NotNull Collection<? extends CallableMemberDescriptor> membersFromSupertypes,
243                @NotNull Collection<? extends CallableMemberDescriptor> membersFromCurrent,
244                @NotNull ClassDescriptor current,
245                @NotNull DescriptorSink sink
246        ) {
247            Collection<CallableMemberDescriptor> notOverridden = new LinkedHashSet<CallableMemberDescriptor>(membersFromSupertypes);
248    
249            for (CallableMemberDescriptor fromCurrent : membersFromCurrent) {
250                Collection<CallableMemberDescriptor> bound =
251                        extractAndBindOverridesForMember(fromCurrent, membersFromSupertypes, current, sink);
252                notOverridden.removeAll(bound);
253            }
254    
255            createAndBindFakeOverrides(current, notOverridden, sink);
256        }
257    
258        private static Collection<CallableMemberDescriptor> extractAndBindOverridesForMember(
259                @NotNull CallableMemberDescriptor fromCurrent,
260                @NotNull Collection<? extends CallableMemberDescriptor> descriptorsFromSuper,
261                @NotNull ClassDescriptor current,
262                @NotNull DescriptorSink sink
263        ) {
264            Collection<CallableMemberDescriptor> bound = new ArrayList<CallableMemberDescriptor>(descriptorsFromSuper.size());
265            for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) {
266                OverrideCompatibilityInfo.Result result = DEFAULT.isOverridableBy(fromSupertype, fromCurrent).getResult();
267    
268                boolean isVisible = Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, fromSupertype, current);
269                switch (result) {
270                    case OVERRIDABLE:
271                        if (isVisible) {
272                            fromCurrent.addOverriddenDescriptor(fromSupertype);
273                        }
274                        bound.add(fromSupertype);
275                        break;
276                    case CONFLICT:
277                        if (isVisible) {
278                            sink.conflict(fromSupertype, fromCurrent);
279                        }
280                        bound.add(fromSupertype);
281                        break;
282                    case INCOMPATIBLE:
283                        break;
284                }
285            }
286            return bound;
287        }
288    
289        private static void createAndBindFakeOverrides(
290                @NotNull ClassDescriptor current,
291                @NotNull Collection<CallableMemberDescriptor> notOverridden,
292                @NotNull DescriptorSink sink
293        ) {
294            Queue<CallableMemberDescriptor> fromSuperQueue = new LinkedList<CallableMemberDescriptor>(notOverridden);
295            while (!fromSuperQueue.isEmpty()) {
296                CallableMemberDescriptor notOverriddenFromSuper = VisibilityUtilKt.findMemberWithMaxVisibility(fromSuperQueue);
297                Collection<CallableMemberDescriptor> overridables =
298                        extractMembersOverridableInBothWays(notOverriddenFromSuper, fromSuperQueue, sink);
299                createAndBindFakeOverride(overridables, current, sink);
300            }
301        }
302    
303        private static boolean isMoreSpecific(@NotNull CallableMemberDescriptor a, @NotNull CallableMemberDescriptor b) {
304            if (a instanceof SimpleFunctionDescriptor) {
305                assert b instanceof SimpleFunctionDescriptor : "b is " + b.getClass();
306    
307                KotlinType aReturnType = a.getReturnType();
308                assert aReturnType != null;
309                KotlinType bReturnType = b.getReturnType();
310                assert bReturnType != null;
311    
312                return KotlinTypeChecker.DEFAULT.isSubtypeOf(aReturnType, bReturnType);
313            }
314            if (a instanceof PropertyDescriptor) {
315                assert b instanceof PropertyDescriptor : "b is " + b.getClass();
316    
317                if (((PropertyDescriptor) a).isVar() || ((PropertyDescriptor) b).isVar()) {
318                    return ((PropertyDescriptor) a).isVar();
319                }
320    
321                // both vals
322                return KotlinTypeChecker.DEFAULT.isSubtypeOf(((PropertyDescriptor) a).getType(), ((PropertyDescriptor) b).getType());
323            }
324            throw new IllegalArgumentException("Unexpected callable: " + a.getClass());
325        }
326    
327        private static CallableMemberDescriptor selectMostSpecificMemberFromSuper(@NotNull Collection<CallableMemberDescriptor> overridables) {
328            CallableMemberDescriptor result = null;
329            for (CallableMemberDescriptor overridable : overridables) {
330                if (result == null || isMoreSpecific(overridable, result)) {
331                    result = overridable;
332                }
333            }
334            return result;
335        }
336    
337        private static void createAndBindFakeOverride(
338                @NotNull Collection<CallableMemberDescriptor> overridables,
339                @NotNull ClassDescriptor current,
340                @NotNull DescriptorSink sink
341        ) {
342            Collection<CallableMemberDescriptor> visibleOverridables = filterVisibleFakeOverrides(current, overridables);
343            boolean allInvisible = visibleOverridables.isEmpty();
344            Collection<CallableMemberDescriptor> effectiveOverridden = allInvisible ? overridables : visibleOverridables;
345    
346            Modality modality = getMinimalModality(effectiveOverridden);
347            Visibility visibility = allInvisible ? Visibilities.INVISIBLE_FAKE : Visibilities.INHERITED;
348            CallableMemberDescriptor mostSpecific = selectMostSpecificMemberFromSuper(effectiveOverridden);
349            CallableMemberDescriptor fakeOverride =
350                    mostSpecific.copy(current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false);
351            for (CallableMemberDescriptor descriptor : effectiveOverridden) {
352                fakeOverride.addOverriddenDescriptor(descriptor);
353            }
354            sink.addFakeOverride(fakeOverride);
355        }
356    
357        @NotNull
358        private static Modality getMinimalModality(@NotNull Collection<CallableMemberDescriptor> descriptors) {
359            Modality modality = Modality.ABSTRACT;
360            for (CallableMemberDescriptor descriptor : descriptors) {
361                if (descriptor.getModality().compareTo(modality) < 0) {
362                    modality = descriptor.getModality();
363                }
364            }
365            return modality;
366        }
367    
368        @NotNull
369        private static Collection<CallableMemberDescriptor> filterVisibleFakeOverrides(
370                @NotNull final ClassDescriptor current,
371                @NotNull Collection<CallableMemberDescriptor> toFilter
372        ) {
373            return CollectionsKt.filter(toFilter, new Function1<CallableMemberDescriptor, Boolean>() {
374                @Override
375                public Boolean invoke(CallableMemberDescriptor descriptor) {
376                    //nested class could capture private member, so check for private visibility added
377                    return !Visibilities.isPrivate(descriptor.getVisibility()) &&
378                           Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, descriptor, current);
379                }
380            });
381        }
382    
383        @NotNull
384        private static Collection<CallableMemberDescriptor> extractMembersOverridableInBothWays(
385                @NotNull CallableMemberDescriptor overrider,
386                @NotNull Queue<CallableMemberDescriptor> extractFrom,
387                @NotNull DescriptorSink sink
388        ) {
389            Collection<CallableMemberDescriptor> overridable = new ArrayList<CallableMemberDescriptor>();
390            overridable.add(overrider);
391            for (Iterator<CallableMemberDescriptor> iterator = extractFrom.iterator(); iterator.hasNext(); ) {
392                CallableMemberDescriptor candidate = iterator.next();
393                if (overrider == candidate) {
394                    iterator.remove();
395                    continue;
396                }
397    
398                OverrideCompatibilityInfo.Result result1 = DEFAULT.isOverridableBy(candidate, overrider).getResult();
399                OverrideCompatibilityInfo.Result result2 = DEFAULT.isOverridableBy(overrider, candidate).getResult();
400                if (result1 == OVERRIDABLE && result2 == OVERRIDABLE) {
401                    overridable.add(candidate);
402                    iterator.remove();
403                }
404                else if (result1 == CONFLICT || result2 == CONFLICT) {
405                    sink.conflict(overrider, candidate);
406                    iterator.remove();
407                }
408            }
409            return overridable;
410        }
411    
412        public static void resolveUnknownVisibilityForMember(
413                @NotNull CallableMemberDescriptor memberDescriptor,
414                @Nullable Function1<CallableMemberDescriptor, Unit> cannotInferVisibility
415        ) {
416            for (CallableMemberDescriptor descriptor : memberDescriptor.getOverriddenDescriptors()) {
417                if (descriptor.getVisibility() == Visibilities.INHERITED) {
418                    resolveUnknownVisibilityForMember(descriptor, cannotInferVisibility);
419                }
420            }
421    
422            if (memberDescriptor.getVisibility() != Visibilities.INHERITED) {
423                return;
424            }
425    
426            Visibility maxVisibility = computeVisibilityToInherit(memberDescriptor);
427            Visibility visibilityToInherit;
428            if (maxVisibility == null) {
429                if (cannotInferVisibility != null) {
430                    cannotInferVisibility.invoke(memberDescriptor);
431                }
432                visibilityToInherit = Visibilities.PUBLIC;
433            }
434            else {
435                visibilityToInherit = maxVisibility;
436            }
437    
438            if (memberDescriptor instanceof PropertyDescriptorImpl) {
439                ((PropertyDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
440                for (PropertyAccessorDescriptor accessor : ((PropertyDescriptor) memberDescriptor).getAccessors()) {
441                    // If we couldn't infer visibility for property, the diagnostic is already reported, no need to report it again on accessors
442                    resolveUnknownVisibilityForMember(accessor, maxVisibility == null ? null : cannotInferVisibility);
443                }
444            }
445            else if (memberDescriptor instanceof FunctionDescriptorImpl) {
446                ((FunctionDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
447            }
448            else {
449                assert memberDescriptor instanceof PropertyAccessorDescriptorImpl;
450                ((PropertyAccessorDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
451            }
452        }
453    
454        @Nullable
455        private static Visibility computeVisibilityToInherit(@NotNull CallableMemberDescriptor memberDescriptor) {
456            Collection<? extends CallableMemberDescriptor> overriddenDescriptors = memberDescriptor.getOverriddenDescriptors();
457            Visibility maxVisibility = findMaxVisibility(overriddenDescriptors);
458            if (maxVisibility == null) {
459                return null;
460            }
461            if (memberDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
462                for (CallableMemberDescriptor overridden : overriddenDescriptors) {
463                    // An implementation (a non-abstract overridden member) of a fake override should have the maximum possible visibility
464                    if (overridden.getModality() != Modality.ABSTRACT && !overridden.getVisibility().equals(maxVisibility)) {
465                        return null;
466                    }
467                }
468                return maxVisibility;
469            }
470            return maxVisibility.normalize();
471        }
472    
473        @Nullable
474        public static Visibility findMaxVisibility(@NotNull Collection<? extends CallableMemberDescriptor> descriptors) {
475            if (descriptors.isEmpty()) {
476                return Visibilities.DEFAULT_VISIBILITY;
477            }
478            Visibility maxVisibility = null;
479            for (CallableMemberDescriptor descriptor : descriptors) {
480                Visibility visibility = descriptor.getVisibility();
481                assert visibility != Visibilities.INHERITED : "Visibility should have been computed for " + descriptor;
482                if (maxVisibility == null) {
483                    maxVisibility = visibility;
484                    continue;
485                }
486                Integer compareResult = Visibilities.compare(visibility, maxVisibility);
487                if (compareResult == null) {
488                    maxVisibility = null;
489                }
490                else if (compareResult > 0) {
491                    maxVisibility = visibility;
492                }
493            }
494            if (maxVisibility == null) {
495                return null;
496            }
497            for (CallableMemberDescriptor descriptor : descriptors) {
498                Integer compareResult = Visibilities.compare(maxVisibility, descriptor.getVisibility());
499                if (compareResult == null || compareResult < 0) {
500                    return null;
501                }
502            }
503            return maxVisibility;
504        }
505    
506        public interface DescriptorSink {
507            void addFakeOverride(@NotNull CallableMemberDescriptor fakeOverride);
508    
509            void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent);
510        }
511    
512        public static class OverrideCompatibilityInfo {
513            public enum Result {
514                OVERRIDABLE,
515                INCOMPATIBLE,
516                CONFLICT,
517            }
518    
519            private static final OverrideCompatibilityInfo SUCCESS = new OverrideCompatibilityInfo(OVERRIDABLE, "SUCCESS");
520    
521            @NotNull
522            public static OverrideCompatibilityInfo success() {
523                return SUCCESS;
524            }
525    
526            @NotNull
527            public static OverrideCompatibilityInfo incompatible(@NotNull String debugMessage) {
528                return new OverrideCompatibilityInfo(INCOMPATIBLE, debugMessage);
529            }
530    
531            @NotNull
532            public static OverrideCompatibilityInfo conflict(@NotNull String debugMessage) {
533                return new OverrideCompatibilityInfo(CONFLICT, debugMessage);
534            }
535    
536            private final Result overridable;
537            private final String debugMessage;
538    
539            public OverrideCompatibilityInfo(@NotNull Result success, @NotNull String debugMessage) {
540                this.overridable = success;
541                this.debugMessage = debugMessage;
542            }
543    
544            @NotNull
545            public Result getResult() {
546                return overridable;
547            }
548    
549            @NotNull
550            public String getDebugMessage() {
551                return debugMessage;
552            }
553        }
554    }