1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 19:48:20 +02:00

Added fixit for missing interface implementation methods

This commit is contained in:
Brian Fiete 2020-02-05 17:07:23 -08:00
parent a296eb0f49
commit 45638a6e7e
7 changed files with 431 additions and 174 deletions

View file

@ -2163,7 +2163,6 @@ namespace IDE.ui
int dataIdx = 3; int dataIdx = 3;
//for (int32 i = 4; i < parts.Count; i++)
while (dataIdx < parts.Count) while (dataIdx < parts.Count)
{ {
int32 lenAdd = 0; int32 lenAdd = 0;
@ -2188,7 +2187,6 @@ namespace IDE.ui
SourceViewPanel sourceViewPanel = IDEApp.sApp.ShowSourceFile(fixitFileName); SourceViewPanel sourceViewPanel = IDEApp.sApp.ShowSourceFile(fixitFileName);
if (sourceViewPanel != null) if (sourceViewPanel != null)
{ {
//var targetContent = mTargetEditWidget.Content as SourceEditWidgetContent;
var targetSourceEditWidgetContent = mTargetEditWidget.Content as SourceEditWidgetContent; var targetSourceEditWidgetContent = mTargetEditWidget.Content as SourceEditWidgetContent;
var history = targetSourceEditWidgetContent.RecordHistoryLocation(); var history = targetSourceEditWidgetContent.RecordHistoryLocation();
history.mNoMerge = true; history.mNoMerge = true;
@ -2196,9 +2194,13 @@ namespace IDE.ui
var editWidgetContent = (SourceEditWidgetContent)sourceViewPanel.mEditWidget.mEditWidgetContent; var editWidgetContent = (SourceEditWidgetContent)sourceViewPanel.mEditWidget.mEditWidgetContent;
editWidgetContent.CursorTextPos = fixitIdx; editWidgetContent.CursorTextPos = fixitIdx;
editWidgetContent.EnsureCursorVisible(true, true); 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) public void InsertSelection(char32 keyChar, String insertType = null, String insertStr = null)
{ {
//Debug.WriteLine("InsertSelection"); //Debug.WriteLine("InsertSelection");
@ -2312,53 +2406,7 @@ namespace IDE.ui
UpdateAsyncInfo();*/ UpdateAsyncInfo();*/
if (implText != null) if (implText != null)
{ InsertImplText(implText);
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 (persistentInvokeSrcPositons != null) if (persistentInvokeSrcPositons != null)
{ {

View file

@ -322,7 +322,6 @@ namespace IDE.ui
if (cmd == "") if (cmd == "")
continue; continue;
//String[] cmdPart = String.StackSplit!(cmd, ' ');
cmdParts.Clear(); cmdParts.Clear();
for (var strView in cmd.Split(' ')) for (var strView in cmd.Split(' '))
cmdParts.Add(strView); cmdParts.Add(strView);

View file

@ -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) void BfAutoComplete::AddOverrides(const StringImpl& filter)
{ {
if (!mIsAutoComplete) if (!mIsAutoComplete)
@ -1941,106 +2111,14 @@ void BfAutoComplete::AddOverrides(const StringImpl& filter)
} }
auto methodInst = methodGroup.mDefault; auto methodInst = methodGroup.mDefault;
if ((methodDef->mIsVirtual) && (!methodDef->mIsOverride)) if ((!methodDef->mIsVirtual) || (methodDef->mIsOverride) || (methodDef->mMethodType != BfMethodType_Normal))
{ continue;
if (methodDef->mMethodType == BfMethodType_Normal)
{
String methodPrefix;
String methodName;
String impString;
bool isAbstract = methodDef->mIsAbstract; StringT<512> insertString;
GetMethodInfo(methodInst, &insertString, &insertString, false);
if (!isAbstract) if (insertString.IsEmpty())
{ continue;
if (!methodInst->mReturnType->IsVoid()) AddEntry(AutoCompleteEntry("override", insertString, NULL), filter);
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 (curType->IsStruct()) if (curType->IsStruct())
@ -2397,6 +2475,127 @@ bool BfAutoComplete::CheckFixit(BfAstNode* node)
return true; return true;
} }
void BfAutoComplete::ChcekInterfaceFixit(BfTypeInstance* typeInstance, BfAstNode* node)
{
if (!CheckFixit(node))
return;
if (typeInstance == NULL)
return;
for (auto& ifaceTypeInst : typeInstance->mInterfaces)
{
Array<BfMethodInstance*> 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<BfBlock>(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) void BfAutoComplete::FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, const StringImpl& fieldName, bool isStatic, BfTypeInstance* referencedFrom)
{ {
if (typeInst == mModule->mContext->mBfObjectType) if (typeInst == mModule->mContext->mBfObjectType)

View file

@ -218,6 +218,7 @@ public:
void UpdateReplaceData(); void UpdateReplaceData();
void AddTypeInstanceEntry(BfTypeInstance* typeInst); void AddTypeInstanceEntry(BfTypeInstance* typeInst);
void CheckDocumentation(AutoCompleteEntry* entry, BfCommentNode* documentation); void CheckDocumentation(AutoCompleteEntry* entry, BfCommentNode* documentation);
bool GetMethodInfo(BfMethodInstance* methodInst, StringImpl* methodName, StringImpl* insertString, bool isExplicitInterface);
public: public:
BfAutoComplete(BfResolveType resolveType = BfResolveType_Autocomplete); BfAutoComplete(BfResolveType resolveType = BfResolveType_Autocomplete);
@ -245,6 +246,7 @@ public:
void CheckLabel(BfIdentifierNode* identifierNode, BfAstNode* precedingNode = NULL); void CheckLabel(BfIdentifierNode* identifierNode, BfAstNode* precedingNode = NULL);
void CheckEmptyStart(BfAstNode* prevNode, BfType* type); void CheckEmptyStart(BfAstNode* prevNode, BfType* type);
bool CheckFixit(BfAstNode* node); 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);

View file

@ -3768,6 +3768,7 @@ void BfCompiler::ProcessAutocompleteTempType()
autoComplete->mInsertEndIdx = nameNode->GetSrcEnd(); autoComplete->mInsertEndIdx = nameNode->GetSrcEnd();
} }
} }
autoComplete->ChcekInterfaceFixit(typeInst, tempTypeDef->mTypeDeclaration->mNameNode);
if (tempTypeDef->mTypeCode == BfTypeCode_TypeAlias) if (tempTypeDef->mTypeCode == BfTypeCode_TypeAlias)
{ {

View file

@ -13982,7 +13982,10 @@ BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericTyp
bool failed = false; bool failed = false;
for (int paramIdx = 0; paramIdx < (int)mIndexerValues.size(); paramIdx++) 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) if (!val)
failed = true; failed = true;
else else
@ -14815,7 +14818,10 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
for (int paramIdx = 0; paramIdx < (int)mIndexerValues.size(); paramIdx++) 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) if (!val)
{ {
mPropDef = NULL; mPropDef = NULL;
@ -14858,7 +14864,6 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
{ {
CheckResultForReading(ptr); CheckResultForReading(ptr);
BfTypedValue leftValue = ptr; BfTypedValue leftValue = ptr;
leftValue = mModule->LoadValue(leftValue);
auto expectedType = ptr.mType; auto expectedType = ptr.mType;
if ((binaryOp == BfBinaryOp_LeftShift) || (binaryOp == BfBinaryOp_RightShift)) if ((binaryOp == BfBinaryOp_LeftShift) || (binaryOp == BfBinaryOp_RightShift))
@ -14907,8 +14912,11 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
} }
if (!handled) if (!handled)
{
leftValue = mModule->LoadValue(leftValue);
PerformBinaryOperation(assignExpr->mLeft, assignExpr->mRight, binaryOp, assignExpr->mOpToken, BfBinOpFlag_ForceLeftType, leftValue, rightValue); PerformBinaryOperation(assignExpr->mLeft, assignExpr->mRight, binaryOp, assignExpr->mOpToken, BfBinOpFlag_ForceLeftType, leftValue, rightValue);
} }
}
if (!handled) if (!handled)
{ {
@ -15969,6 +15977,7 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
argVal = mModule->GetDefaultTypedValue(mModule->mContext->mBfObjectType); argVal = mModule->GetDefaultTypedValue(mModule->mContext->mBfObjectType);
} }
BfResolvedArg resolvedArg; BfResolvedArg resolvedArg;
resolvedArg.mExpression = expr;
resolvedArg.mTypedValue = argVal; resolvedArg.mTypedValue = argVal;
mIndexerValues.push_back(resolvedArg); mIndexerValues.push_back(resolvedArg);
} }

View file

@ -4068,7 +4068,8 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
} }
else 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 ((matchedMethod != NULL) && (error != NULL))
{ {
if (hadPubFailure) if (hadPubFailure)
@ -6179,8 +6180,6 @@ void BfModule::CheckTypeRefFixit(BfAstNode* typeRef, const char* appendName)
std::set<String> fixitNamespaces; std::set<String> fixitNamespaces;
//TODO: Do proper value for numGenericArgs //TODO: Do proper value for numGenericArgs
//mSystem->FindFixitNamespaces(typeName, -1, typeRef->GetSourceData()->mProject, fixitNamespaces);
mSystem->FindFixitNamespaces(typeName, -1, mCompiler->mResolvePassData->mParser->mProject, fixitNamespaces); mSystem->FindFixitNamespaces(typeName, -1, mCompiler->mResolvePassData->mParser->mProject, fixitNamespaces);
int insertLoc = 0; int insertLoc = 0;