From 45638a6e7e66b5a0772a2e9211131d1aedfe28f7 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Wed, 5 Feb 2020 17:07:23 -0800 Subject: [PATCH] Added fixit for missing interface implementation methods --- IDE/src/ui/AutoComplete.bf | 154 ++++++--- IDE/src/ui/SourceEditWidgetContent.bf | 1 - IDEHelper/Compiler/BfAutoComplete.cpp | 399 +++++++++++++++++------ IDEHelper/Compiler/BfAutoComplete.h | 4 +- IDEHelper/Compiler/BfCompiler.cpp | 5 +- IDEHelper/Compiler/BfExprEvaluator.cpp | 17 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 25 +- 7 files changed, 431 insertions(+), 174 deletions(-) diff --git a/IDE/src/ui/AutoComplete.bf b/IDE/src/ui/AutoComplete.bf index 3d2604bd..3bbec245 100644 --- a/IDE/src/ui/AutoComplete.bf +++ b/IDE/src/ui/AutoComplete.bf @@ -2163,7 +2163,6 @@ namespace IDE.ui int dataIdx = 3; - //for (int32 i = 4; i < parts.Count; i++) while (dataIdx < parts.Count) { int32 lenAdd = 0; @@ -2188,17 +2187,20 @@ namespace IDE.ui SourceViewPanel sourceViewPanel = IDEApp.sApp.ShowSourceFile(fixitFileName); if (sourceViewPanel != null) { - //var targetContent = mTargetEditWidget.Content as SourceEditWidgetContent; var targetSourceEditWidgetContent = mTargetEditWidget.Content as SourceEditWidgetContent; var history = targetSourceEditWidgetContent.RecordHistoryLocation(); history.mNoMerge = true; var editWidgetContent = (SourceEditWidgetContent)sourceViewPanel.mEditWidget.mEditWidgetContent; - editWidgetContent.CursorTextPos = fixitIdx; + editWidgetContent.CursorTextPos = fixitIdx; editWidgetContent.EnsureCursorVisible(true, true); - editWidgetContent.PasteText(fixitInsert, fixitInsert.StartsWith("\n")); - fixitIdx = (int32)editWidgetContent.CursorTextPos + lenAdd; + if (fixitInsert.StartsWith('\n')) + editWidgetContent.PasteText(fixitInsert, fixitInsert.StartsWith("\n")); + else + InsertImplText(fixitInsert); + + fixitIdx = (.)editWidgetContent.CursorTextPos; } } @@ -2213,6 +2215,98 @@ namespace IDE.ui }*/ } + void InsertImplText(String implText) + { + + var sourceEditWidgetContent = mTargetEditWidget.Content as SourceEditWidgetContent; + /*sourceEditWidgetContent.ClearLine(); + sourceEditWidgetContent.InsertAtCursor("ABC\nDEF\nGHI"); + return;*/ + + String implSect = scope .(); + + int startIdx = 0; + for (int i < implText.Length) + { + char8 c = implText[i]; + if ((c == '\t') || (c == '\b') || (c == '\r') || (c == '\f')) + { + implSect.Clear(); + implSect.Append(implText, startIdx, i - startIdx); + if (!implSect.IsEmpty) + { + sourceEditWidgetContent.InsertAtCursor(implSect); + } + + if (c == '\f') + { + if (!sourceEditWidgetContent.IsLineWhiteSpace(sourceEditWidgetContent.CursorLineAndColumn.mLine)) + { + sourceEditWidgetContent.InsertAtCursor("\n"); + } + if (!sourceEditWidgetContent.IsLineWhiteSpace(sourceEditWidgetContent.CursorLineAndColumn.mLine)) + { + int prevPos = sourceEditWidgetContent.CursorTextPos; + sourceEditWidgetContent.InsertAtCursor("\n"); + sourceEditWidgetContent.CursorTextPos = prevPos; + } + sourceEditWidgetContent.CursorToLineEnd(); + /*if (!sourceEditWidgetContent.IsLineWhiteSpace(sourceEditWidgetContent.CursorLineAndColumn.mLine)) + { + sourceEditWidgetContent.InsertText(sourceEditWidgetContent.CursorTextPos + 1, "\n"); + sourceEditWidgetContent.ContentChanged(); + }*/ + //return; + + //sourceEditWidgetContent.GetLineText(sourceEditWidgetContent.CursorLineAndColumn.mLine, ) + + //sourceEditWidgetContent.InsertAtCursor("ABC\n"); + } + else if (c == '\t') + { + sourceEditWidgetContent.InsertAtCursor("\n"); + sourceEditWidgetContent.CursorToLineEnd(); + sourceEditWidgetContent.OpenCodeBlock(); + } + else if (c == '\r') + { + sourceEditWidgetContent.InsertAtCursor("\n"); + sourceEditWidgetContent.CursorToLineEnd(); + } + else if (c == '\b') + { + int cursorPos = sourceEditWidgetContent.CursorTextPos; + while (cursorPos < sourceEditWidgetContent.mData.mTextLength) + { + char8 checkC = sourceEditWidgetContent.mData.mText[cursorPos].mChar; + cursorPos++; + if (checkC == '}') + break; + } + sourceEditWidgetContent.CursorTextPos = cursorPos; + } + else + { + let lc = sourceEditWidgetContent.CursorLineAndColumn; + sourceEditWidgetContent.CursorLineAndColumn = .(lc.mLine + 1, 0); + sourceEditWidgetContent.CursorToLineEnd(); + sourceEditWidgetContent.InsertAtCursor("\n"); + sourceEditWidgetContent.CursorToLineEnd(); + } + + startIdx = i + 1; + } + } + + implSect.Clear(); + implSect.Append(implText, startIdx, implText.Length - startIdx); + if (!implSect.IsEmpty) + { + sourceEditWidgetContent.InsertAtCursor(implSect); + } + } + + public void InsertSelection(char32 keyChar, String insertType = null, String insertStr = null) { //Debug.WriteLine("InsertSelection"); @@ -2311,54 +2405,8 @@ namespace IDE.ui /*if (mIsAsync) UpdateAsyncInfo();*/ - if (implText != null) - { - String implSect = scope .(); - - int startIdx = 0; - for (int i < implText.Length) - { - char8 c = implText[i]; - if ((c == '\t') || (c == '\b') || (c == '\r')) - { - implSect.Clear(); - implSect.Append(implText, startIdx, i - startIdx); - if (!implSect.IsEmpty) - { - sourceEditWidgetContent.InsertAtCursor(implSect); - } - - if (c == '\t') - { - sourceEditWidgetContent.InsertAtCursor("\n"); - sourceEditWidgetContent.CursorToLineEnd(); - sourceEditWidgetContent.OpenCodeBlock(); - } - else if (c == '\r') - { - sourceEditWidgetContent.InsertAtCursor("\n"); - sourceEditWidgetContent.CursorToLineEnd(); - } - else - { - let lc = sourceEditWidgetContent.CursorLineAndColumn; - sourceEditWidgetContent.CursorLineAndColumn = .(lc.mLine + 1, 0); - sourceEditWidgetContent.CursorToLineEnd(); - sourceEditWidgetContent.InsertAtCursor("\n"); - sourceEditWidgetContent.CursorToLineEnd(); - } - - startIdx = i + 1; - } - } - - implSect.Clear(); - implSect.Append(implText, startIdx, implText.Length - startIdx); - if (!implSect.IsEmpty) - { - sourceEditWidgetContent.InsertAtCursor(implSect); - } - } + if (implText != null) + InsertImplText(implText); if (persistentInvokeSrcPositons != null) { diff --git a/IDE/src/ui/SourceEditWidgetContent.bf b/IDE/src/ui/SourceEditWidgetContent.bf index d6d31efe..7248ff11 100644 --- a/IDE/src/ui/SourceEditWidgetContent.bf +++ b/IDE/src/ui/SourceEditWidgetContent.bf @@ -322,7 +322,6 @@ namespace IDE.ui if (cmd == "") continue; - //String[] cmdPart = String.StackSplit!(cmd, ' '); cmdParts.Clear(); for (var strView in cmd.Split(' ')) cmdParts.Add(strView); diff --git a/IDEHelper/Compiler/BfAutoComplete.cpp b/IDEHelper/Compiler/BfAutoComplete.cpp index b3a2ec85..865b259a 100644 --- a/IDEHelper/Compiler/BfAutoComplete.cpp +++ b/IDEHelper/Compiler/BfAutoComplete.cpp @@ -1906,6 +1906,176 @@ void BfAutoComplete::CheckNode(BfAstNode* node) } } +bool BfAutoComplete::GetMethodInfo(BfMethodInstance* methodInst, StringImpl* showString, StringImpl* insertString, bool isExplicitInterface) +{ + auto methodDef = methodInst->mMethodDef; + bool isInterface = methodInst->GetOwner()->IsInterface(); + + if (methodDef->mMethodType == BfMethodType_Normal) + { + StringT<128> methodPrefix; + StringT<128> methodName; + StringT<256> impString; + + bool isAbstract = (methodDef->mIsAbstract) && (!isInterface); + + if (!isAbstract) + { + if (isInterface) + { + if (!methodInst->mReturnType->IsVoid()) + impString += "return default;"; + } + else + { + if (!methodInst->mReturnType->IsVoid()) + impString = "return "; + + impString += "base."; + impString += methodDef->mName; + impString += "("; + } + } + + auto methodDeclaration = methodDef->GetMethodDeclaration(); + + if (isInterface) + { + if (!isExplicitInterface) + methodPrefix += "public "; + } + else if (methodDeclaration->mProtectionSpecifier != NULL) + methodPrefix += methodDeclaration->mProtectionSpecifier->ToString() + " "; + if (!isInterface) + methodPrefix += "override "; + methodPrefix += mModule->TypeToString(methodInst->mReturnType, BfTypeNameFlag_ReduceName); + methodPrefix += " "; + if (isExplicitInterface) + { + methodName += mModule->TypeToString(methodInst->GetOwner(), BfTypeNameFlag_ReduceName); + methodName += "."; + } + + methodName += methodDef->mName; + methodName += "("; + for (int paramIdx = 0; paramIdx < (int)methodInst->GetParamCount(); paramIdx++) + { + if (paramIdx > 0) + { + methodName += ", "; + if ((!isAbstract) && (!isInterface)) + impString += ", "; + } + methodName += mModule->TypeToString(methodInst->GetParamType(paramIdx), BfTypeNameFlag_ReduceName); + methodName += " "; + methodName += methodDef->mParams[paramIdx]->mName; + + if ((!isAbstract) && (!isInterface)) + impString += methodDef->mParams[paramIdx]->mName; + } + methodName += ")"; + + if ((!isAbstract) && (!isInterface)) + impString += ");"; + + if (showString != NULL) + *showString += methodName; + if (insertString != NULL) + { + if (showString == insertString) + *insertString += "\t"; + + *insertString += methodPrefix + methodName + "\t" + impString; + } + + return true; + } + else if ((methodDef->mMethodType == BfMethodType_PropertyGetter) || (methodDef->mMethodType == BfMethodType_PropertySetter)) + { + auto propDeclaration = methodDef->GetPropertyDeclaration(); + bool hasGet = propDeclaration->GetMethod("get") != NULL; + bool hasSet = propDeclaration->GetMethod("set") != NULL; + + if ((methodDef->mMethodType == BfMethodType_PropertyGetter) || (!hasGet)) + { + StringT<128> propName; + StringT<256> impl; + + propDeclaration->mNameNode->ToString(propName); + + bool isAbstract = methodDef->mIsAbstract; + + if (propDeclaration->mProtectionSpecifier != NULL) + impl += propDeclaration->mProtectionSpecifier->ToString() + " "; + if (!isInterface) + impl += "override "; + + BfType* propType = methodInst->mReturnType; + if (methodDef->mMethodType == BfMethodType_PropertySetter) + propType = methodInst->GetParamType(0); + impl += mModule->TypeToString(propType, BfTypeNameFlag_ReduceName); + impl += " "; + if (isExplicitInterface) + { + impl += mModule->TypeToString(methodInst->GetOwner(), BfTypeNameFlag_ReduceName); + impl += "."; + } + + impl += propName; + impl += "\t"; + if (hasGet) + { + impl += "get\t"; + if (!isAbstract) + { + if (isInterface) + { + impl += "return default;"; + } + else + { + impl += "return base."; + impl += propName; + impl += ";"; + } + } + impl += "\b"; + } + if (hasSet) + { + if (hasGet) + impl += "\r\r"; + + impl += "set\t"; + if (!isAbstract) + { + if (!isInterface) + { + impl += "base."; + impl += propName; + impl += " = value;"; + } + } + + impl += "\b"; + } + + if (showString != NULL) + *showString += propName; + if (insertString != NULL) + { + if (showString == insertString) + *insertString += "\t"; + *insertString += impl; + } + + return true; + } + } + + return false; +} + void BfAutoComplete::AddOverrides(const StringImpl& filter) { if (!mIsAutoComplete) @@ -1941,106 +2111,14 @@ void BfAutoComplete::AddOverrides(const StringImpl& filter) } auto methodInst = methodGroup.mDefault; - if ((methodDef->mIsVirtual) && (!methodDef->mIsOverride)) - { - if (methodDef->mMethodType == BfMethodType_Normal) - { - String methodPrefix; - String methodName; - String impString; - - bool isAbstract = methodDef->mIsAbstract; - - if (!isAbstract) - { - if (!methodInst->mReturnType->IsVoid()) - impString = "return "; - - impString += "base."; - impString += methodDef->mName; - impString += "("; - } - - auto methodDeclaration = methodDef->GetMethodDeclaration(); - if (methodDeclaration->mProtectionSpecifier != NULL) - methodPrefix += methodDeclaration->mProtectionSpecifier->ToString() + " "; - methodPrefix += "override "; - methodPrefix += mModule->TypeToString(methodInst->mReturnType, BfTypeNameFlag_ReduceName); - methodPrefix += " "; - methodName += methodDef->mName; - methodName += "("; - for (int paramIdx = 0; paramIdx < (int)methodInst->GetParamCount(); paramIdx++) - { - if (paramIdx > 0) - { - methodName += ", "; - if (!isAbstract) - impString += ", "; - } - methodName += mModule->TypeToString(methodInst->GetParamType(paramIdx), BfTypeNameFlag_ReduceName); - methodName += " "; - methodName += methodDef->mParams[paramIdx]->mName; - - if (!isAbstract) - impString += methodDef->mParams[paramIdx]->mName; - } - methodName += ")"; - - if (!isAbstract) - impString += ");"; - - AddEntry(AutoCompleteEntry("override", methodName + "\t" + methodPrefix + methodName + "\t" + impString, NULL), filter); - } - else if ((methodDef->mMethodType == BfMethodType_PropertyGetter) || (methodDef->mMethodType == BfMethodType_PropertySetter)) - { - auto propDeclaration = methodDef->GetPropertyDeclaration(); - bool hasGet = propDeclaration->GetMethod("get") != NULL; - bool hasSet = propDeclaration->GetMethod("set") != NULL; - - if ((methodDef->mMethodType == BfMethodType_PropertyGetter) || (!hasGet)) - { - String propName; - String impl; - - propDeclaration->mNameNode->ToString(propName); - - bool isAbstract = methodDef->mIsAbstract; - - if (propDeclaration->mProtectionSpecifier != NULL) - impl += propDeclaration->mProtectionSpecifier->ToString() + " "; - impl += "override "; - impl += mModule->TypeToString(methodInst->mReturnType, BfTypeNameFlag_ReduceName); - impl += " "; - impl += propName; - impl += "\t"; - if (hasGet) - { - impl += "get\t"; - if (!isAbstract) - { - impl += "return base."; - impl += propName; - impl += ";"; - } - } - if (hasSet) - { - if (hasGet) - impl += "\b\r"; - - impl += "set\t"; - if (!isAbstract) - { - impl += "base."; - impl += propName; - impl += " = value;"; - } - } - - AddEntry(AutoCompleteEntry("override", propName + "\t" + impl, NULL), filter); - } - } - } + if ((!methodDef->mIsVirtual) || (methodDef->mIsOverride) || (methodDef->mMethodType != BfMethodType_Normal)) + continue; + + StringT<512> insertString; + GetMethodInfo(methodInst, &insertString, &insertString, false); + if (insertString.IsEmpty()) + continue; + AddEntry(AutoCompleteEntry("override", insertString, NULL), filter); } if (curType->IsStruct()) @@ -2397,6 +2475,127 @@ bool BfAutoComplete::CheckFixit(BfAstNode* node) return true; } +void BfAutoComplete::ChcekInterfaceFixit(BfTypeInstance* typeInstance, BfAstNode* node) +{ + if (!CheckFixit(node)) + return; + if (typeInstance == NULL) + return; + + for (auto& ifaceTypeInst : typeInstance->mInterfaces) + { + Array missingMethods; + + auto ifaceInst = ifaceTypeInst.mInterfaceType; + int startIdx = ifaceTypeInst.mStartInterfaceTableIdx; + int iMethodCount = (int)ifaceInst->mMethodInstanceGroups.size(); + auto declTypeDef = ifaceTypeInst.mDeclaringType; + + for (int iMethodIdx = 0; iMethodIdx < iMethodCount; iMethodIdx++) + { + auto matchedMethodRef = &typeInstance->mInterfaceMethodTable[iMethodIdx + startIdx].mMethodRef; + BfMethodInstance* matchedMethod = *matchedMethodRef; + auto ifaceMethodInst = ifaceInst->mMethodInstanceGroups[iMethodIdx].mDefault; + if (ifaceMethodInst == NULL) + continue; + + // Don't even try to match generics + if (!ifaceMethodInst->mMethodDef->mGenericParams.IsEmpty()) + continue; + auto iReturnType = ifaceMethodInst->mReturnType; + if (iReturnType->IsSelf()) + iReturnType = typeInstance; + + if (ifaceMethodInst->mMethodDef->mIsOverride) + continue; // Don't consider overrides here + + // If we have "ProjA depends on LibBase", "ProjB depends on LibBase", then a type ClassC in LibBase implementing IFaceD, + // where IFaceD gets extended with MethodE in ProjA, an implementing MethodE is still required to exist on ClassC -- + // the visibility is bidirectional. A type ClassF implementing IFaceD inside ProjB will not be required to implement + // MethodE, however + if ((!ifaceInst->IsTypeMemberAccessible(ifaceMethodInst->mMethodDef->mDeclaringType, ifaceTypeInst.mDeclaringType)) && + (!ifaceInst->IsTypeMemberAccessible(ifaceTypeInst.mDeclaringType, ifaceMethodInst->mMethodDef->mDeclaringType))) + continue; + + if (!ifaceInst->IsTypeMemberIncluded(ifaceMethodInst->mMethodDef->mDeclaringType, ifaceTypeInst.mDeclaringType)) + continue; + + bool hadMatch = matchedMethod != NULL; + bool hadPubFailure = false; + bool hadMutFailure = false; + + if (!hadMatch) + missingMethods.Add(ifaceMethodInst); + } + + if (!missingMethods.IsEmpty()) + { + BfTypeDeclaration* typeDecl = declTypeDef->mTypeDeclaration; + BfTokenNode* openNode = NULL; + BfTokenNode* closeNode = NULL; + if (auto blockNode = BfNodeDynCast(typeDecl->mDefineNode)) + { + openNode = blockNode->mOpenBrace; + closeNode = blockNode->mCloseBrace; + } + + BfParserData* parser = declTypeDef->mTypeDeclaration->GetSourceData()->ToParserData(); + if ((parser != NULL) && (closeNode != NULL)) + { + int startPos = openNode->mSrcStart + 1; + int insertPos = closeNode->mSrcStart; + while (insertPos > startPos) + { + char prevC = parser->mSrc[insertPos - 1]; + if (prevC == '\n') + break; + insertPos--; + } + if (insertPos > startPos) + insertPos--; + + bool wantsBreak = false; + String insertStr = "\f"; + for (auto methodInst : missingMethods) + { + if (wantsBreak) + { + insertStr += "\r\r"; + wantsBreak = false; + } + if (GetMethodInfo(methodInst, NULL, &insertStr, false)) + { + insertStr += "\b"; + wantsBreak = true; + } + } + + wantsBreak = false; + String explicitInsertStr = "\f"; + for (auto methodInst : missingMethods) + { + if (wantsBreak) + { + explicitInsertStr += "\r\r"; + wantsBreak = false; + } + if (GetMethodInfo(methodInst, NULL, &explicitInsertStr, true)) + { + explicitInsertStr += "\b"; + wantsBreak = true; + } + } + + + mCompiler->mResolvePassData->mAutoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Implement interface '%s'\tusing|%s|%d|%s", + mModule->TypeToString(ifaceInst).c_str(), parser->mFileName.c_str(), insertPos, insertStr.c_str()).c_str())); + mCompiler->mResolvePassData->mAutoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Implement interface '%s' explicitly\tusing|%s|%d|%s", + mModule->TypeToString(ifaceInst).c_str(), parser->mFileName.c_str(), insertPos, explicitInsertStr.c_str()).c_str())); + } + } + } +} + void BfAutoComplete::FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, const StringImpl& fieldName, bool isStatic, BfTypeInstance* referencedFrom) { if (typeInst == mModule->mContext->mBfObjectType) diff --git a/IDEHelper/Compiler/BfAutoComplete.h b/IDEHelper/Compiler/BfAutoComplete.h index 4925d84b..19111214 100644 --- a/IDEHelper/Compiler/BfAutoComplete.h +++ b/IDEHelper/Compiler/BfAutoComplete.h @@ -218,6 +218,7 @@ public: void UpdateReplaceData(); void AddTypeInstanceEntry(BfTypeInstance* typeInst); void CheckDocumentation(AutoCompleteEntry* entry, BfCommentNode* documentation); + bool GetMethodInfo(BfMethodInstance* methodInst, StringImpl* methodName, StringImpl* insertString, bool isExplicitInterface); public: BfAutoComplete(BfResolveType resolveType = BfResolveType_Autocomplete); @@ -245,8 +246,9 @@ public: void CheckLabel(BfIdentifierNode* identifierNode, BfAstNode* precedingNode = NULL); void CheckEmptyStart(BfAstNode* prevNode, BfType* type); bool CheckFixit(BfAstNode* node); + void ChcekInterfaceFixit(BfTypeInstance* typeInstance, BfAstNode* node); - void FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, const StringImpl& fieldName, bool isStatic, BfTypeInstance* referencedFrom); + void FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, const StringImpl& fieldName, bool isStatic, BfTypeInstance* referencedFrom); }; diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index bbe00723..edddd59a 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -3766,8 +3766,9 @@ void BfCompiler::ProcessAutocompleteTempType() autoComplete->mDefType = actualTypeDef; autoComplete->mInsertStartIdx = nameNode->GetSrcStart(); autoComplete->mInsertEndIdx = nameNode->GetSrcEnd(); - } - } + } + } + autoComplete->ChcekInterfaceFixit(typeInst, tempTypeDef->mTypeDeclaration->mNameNode); if (tempTypeDef->mTypeCode == BfTypeCode_TypeAlias) { diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 2801430f..1b8fc9d1 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -13982,7 +13982,10 @@ BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericTyp bool failed = false; for (int paramIdx = 0; paramIdx < (int)mIndexerValues.size(); paramIdx++) { - auto val = mModule->Cast(mPropSrc, mIndexerValues[paramIdx].mTypedValue, methodInstance.mMethodInstance->GetParamType(paramIdx)); + auto refNode = mIndexerValues[paramIdx].mExpression; + if (refNode == NULL) + refNode = mPropSrc; + auto val = mModule->Cast(refNode, mIndexerValues[paramIdx].mTypedValue, methodInstance.mMethodInstance->GetParamType(paramIdx)); if (!val) failed = true; else @@ -14815,7 +14818,10 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool for (int paramIdx = 0; paramIdx < (int)mIndexerValues.size(); paramIdx++) { - auto val = mModule->Cast(mPropSrc, mIndexerValues[paramIdx].mTypedValue, methodInstance.mMethodInstance->GetParamType(paramIdx)); + auto refNode = mIndexerValues[paramIdx].mExpression; + if (refNode == NULL) + refNode = mPropSrc; + auto val = mModule->Cast(refNode, mIndexerValues[paramIdx].mTypedValue, methodInstance.mMethodInstance->GetParamType(paramIdx)); if (!val) { mPropDef = NULL; @@ -14858,8 +14864,7 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool { CheckResultForReading(ptr); BfTypedValue leftValue = ptr; - leftValue = mModule->LoadValue(leftValue); - + auto expectedType = ptr.mType; if ((binaryOp == BfBinaryOp_LeftShift) || (binaryOp == BfBinaryOp_RightShift)) expectedType = mModule->GetPrimitiveType(BfTypeCode_IntPtr); @@ -14907,7 +14912,10 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool } if (!handled) + { + leftValue = mModule->LoadValue(leftValue); PerformBinaryOperation(assignExpr->mLeft, assignExpr->mRight, binaryOp, assignExpr->mOpToken, BfBinOpFlag_ForceLeftType, leftValue, rightValue); + } } if (!handled) @@ -15969,6 +15977,7 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr) argVal = mModule->GetDefaultTypedValue(mModule->mContext->mBfObjectType); } BfResolvedArg resolvedArg; + resolvedArg.mExpression = expr; resolvedArg.mTypedValue = argVal; mIndexerValues.push_back(resolvedArg); } diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index e933a5c8..fa12c453 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -3815,7 +3815,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) } if ((!typeInstance->IsInterface()) && (!typeInstance->IsUnspecializedTypeVariation()) && (!isBoxed)) - { + { if (!typeInstance->mTypeDef->mIsAbstract) { for (int methodIdx = 0; methodIdx < (int) typeInstance->mVirtualMethodTable.size(); methodIdx++) @@ -3896,7 +3896,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) } for (auto& ifaceTypeInst : typeInstance->mInterfaces) - { + { auto ifaceInst = ifaceTypeInst.mInterfaceType; int startIdx = ifaceTypeInst.mStartInterfaceTableIdx; int iMethodCount = (int)ifaceInst->mMethodInstanceGroups.size(); @@ -3978,7 +3978,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) { bool searchFailed = false; for (auto& checkIFaceTypeInst : typeInstance->mInterfaces) - { + { auto checkIFaceInst = checkIFaceTypeInst.mInterfaceType; int checkStartIdx = checkIFaceTypeInst.mStartInterfaceTableIdx; int checkIMethodCount = (int)checkIFaceInst->mMethodInstanceGroups.size(); @@ -4067,8 +4067,9 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) } } else - { - BfError* error = Fail(StrFormat("'%s' does not implement interface member '%s'", TypeToString(typeInstance).c_str(), MethodToString(ifaceMethodInst).c_str()), declTypeDef->mTypeDeclaration->mNameNode, true); + { + BfTypeDeclaration* typeDecl = declTypeDef->mTypeDeclaration; + BfError* error = Fail(StrFormat("'%s' does not implement interface member '%s'", TypeToString(typeInstance).c_str(), MethodToString(ifaceMethodInst).c_str()), typeDecl->mNameNode, true); if ((matchedMethod != NULL) && (error != NULL)) { if (hadPubFailure) @@ -4094,16 +4095,16 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) if ((ifaceMethodInst->mVirtualTableIdx != -1) && (ifaceMethodInst->mReturnType->IsInterface())) mCompiler->mPassInstance->MoreInfo("Declare the interface method as 'concrete' to allow matching concrete return values", ifaceMethodInst->mMethodDef->GetMethodDeclaration()->mVirtualSpecifier); } - } + } } } // Clear out the entry *matchedMethodRef = BfMethodRef(); - } - } - } - } + } + } + } + } ambiguityContext.Finish(); CheckAddFailType(); @@ -6178,9 +6179,7 @@ void BfModule::CheckTypeRefFixit(BfAstNode* typeRef, const char* appendName) std::set fixitNamespaces; - //TODO: Do proper value for numGenericArgs - - //mSystem->FindFixitNamespaces(typeName, -1, typeRef->GetSourceData()->mProject, fixitNamespaces); + //TODO: Do proper value for numGenericArgs mSystem->FindFixitNamespaces(typeName, -1, mCompiler->mResolvePassData->mParser->mProject, fixitNamespaces); int insertLoc = 0;