mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Added fixit for missing interface implementation methods
This commit is contained in:
parent
a296eb0f49
commit
45638a6e7e
7 changed files with 431 additions and 174 deletions
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<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)
|
||||
{
|
||||
if (typeInst == mModule->mContext->mBfObjectType)
|
||||
|
|
|
@ -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);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<String> 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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue