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