| 3507 | } |
| 3508 | |
| 3509 | void BfAutoComplete::CheckInterfaceFixit(BfTypeInstance* typeInstance, BfAstNode* node) |
| 3510 | { |
| 3511 | if (!CheckFixit(node)) |
| 3512 | return; |
| 3513 | if (typeInstance == NULL) |
| 3514 | return; |
| 3515 | |
| 3516 | if (typeInstance->IsInterface()) |
| 3517 | return; |
| 3518 | |
| 3519 | for (auto& ifaceTypeInst : typeInstance->mInterfaces) |
| 3520 | { |
| 3521 | Array<BfMethodInstance*> missingMethods; |
| 3522 | |
| 3523 | auto ifaceInst = ifaceTypeInst.mInterfaceType; |
| 3524 | int startIdx = ifaceTypeInst.mStartInterfaceTableIdx; |
| 3525 | int iMethodCount = (int)ifaceInst->mMethodInstanceGroups.size(); |
| 3526 | auto declTypeDef = ifaceTypeInst.mDeclaringType; |
| 3527 | |
| 3528 | for (int iMethodIdx = 0; iMethodIdx < iMethodCount; iMethodIdx++) |
| 3529 | { |
| 3530 | auto matchedMethodRef = &typeInstance->mInterfaceMethodTable[iMethodIdx + startIdx].mMethodRef; |
| 3531 | BfMethodInstance* matchedMethod = *matchedMethodRef; |
| 3532 | auto ifaceMethodInst = ifaceInst->mMethodInstanceGroups[iMethodIdx].mDefault; |
| 3533 | if (ifaceMethodInst == NULL) |
| 3534 | continue; |
| 3535 | |
| 3536 | auto iReturnType = ifaceMethodInst->mReturnType; |
| 3537 | if (iReturnType->IsSelf()) |
| 3538 | iReturnType = typeInstance; |
| 3539 | |
| 3540 | if (ifaceMethodInst->mMethodDef->mIsOverride) |
| 3541 | continue; // Don't consider overrides here |
| 3542 | |
| 3543 | // If we have "ProjA depends on LibBase", "ProjB depends on LibBase", then a type ClassC in LibBase implementing IFaceD, |
| 3544 | // where IFaceD gets extended with MethodE in ProjA, an implementing MethodE is still required to exist on ClassC -- |
| 3545 | // the visibility is bidirectional. A type ClassF implementing IFaceD inside ProjB will not be required to implement |
| 3546 | // MethodE, however |
| 3547 | if ((!ifaceInst->IsTypeMemberAccessible(ifaceMethodInst->mMethodDef->mDeclaringType, ifaceTypeInst.mDeclaringType)) && |
| 3548 | (!ifaceInst->IsTypeMemberAccessible(ifaceTypeInst.mDeclaringType, ifaceMethodInst->mMethodDef->mDeclaringType))) |
| 3549 | continue; |
| 3550 | |
| 3551 | if (!ifaceInst->IsTypeMemberIncluded(ifaceMethodInst->mMethodDef->mDeclaringType, ifaceTypeInst.mDeclaringType)) |
| 3552 | continue; |
| 3553 | |
| 3554 | bool hadMatch = matchedMethod != NULL; |
| 3555 | bool hadPubFailure = false; |
| 3556 | bool hadMutFailure = false; |
| 3557 | |
| 3558 | if (!hadMatch) |
| 3559 | missingMethods.Add(ifaceMethodInst); |
| 3560 | } |
| 3561 | |
| 3562 | if (!missingMethods.IsEmpty()) |
| 3563 | { |
| 3564 | BfParserData* parser = declTypeDef->mTypeDeclaration->GetSourceData()->ToParserData(); |
| 3565 | if (parser != NULL) |
| 3566 | { |
no test coverage detected