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;
|
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,17 +2187,20 @@ 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;
|
||||||
|
|
||||||
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");
|
||||||
|
@ -2311,54 +2405,8 @@ namespace IDE.ui
|
||||||
/*if (mIsAsync)
|
/*if (mIsAsync)
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
|
||||||
{
|
StringT<512> insertString;
|
||||||
String methodPrefix;
|
GetMethodInfo(methodInst, &insertString, &insertString, false);
|
||||||
String methodName;
|
if (insertString.IsEmpty())
|
||||||
String impString;
|
continue;
|
||||||
|
AddEntry(AutoCompleteEntry("override", insertString, NULL), filter);
|
||||||
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 (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)
|
||||||
|
|
|
@ -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,8 +246,9 @@ 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);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3766,8 +3766,9 @@ void BfCompiler::ProcessAutocompleteTempType()
|
||||||
autoComplete->mDefType = actualTypeDef;
|
autoComplete->mDefType = actualTypeDef;
|
||||||
autoComplete->mInsertStartIdx = nameNode->GetSrcStart();
|
autoComplete->mInsertStartIdx = nameNode->GetSrcStart();
|
||||||
autoComplete->mInsertEndIdx = nameNode->GetSrcEnd();
|
autoComplete->mInsertEndIdx = nameNode->GetSrcEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
autoComplete->ChcekInterfaceFixit(typeInst, tempTypeDef->mTypeDeclaration->mNameNode);
|
||||||
|
|
||||||
if (tempTypeDef->mTypeCode == BfTypeCode_TypeAlias)
|
if (tempTypeDef->mTypeCode == BfTypeCode_TypeAlias)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,8 +14864,7 @@ 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))
|
||||||
expectedType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
|
expectedType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
|
||||||
|
@ -14907,7 +14912,10 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3815,7 +3815,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!typeInstance->IsInterface()) && (!typeInstance->IsUnspecializedTypeVariation()) && (!isBoxed))
|
if ((!typeInstance->IsInterface()) && (!typeInstance->IsUnspecializedTypeVariation()) && (!isBoxed))
|
||||||
{
|
{
|
||||||
if (!typeInstance->mTypeDef->mIsAbstract)
|
if (!typeInstance->mTypeDef->mIsAbstract)
|
||||||
{
|
{
|
||||||
for (int methodIdx = 0; methodIdx < (int) typeInstance->mVirtualMethodTable.size(); methodIdx++)
|
for (int methodIdx = 0; methodIdx < (int) typeInstance->mVirtualMethodTable.size(); methodIdx++)
|
||||||
|
@ -3896,7 +3896,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& ifaceTypeInst : typeInstance->mInterfaces)
|
for (auto& ifaceTypeInst : typeInstance->mInterfaces)
|
||||||
{
|
{
|
||||||
auto ifaceInst = ifaceTypeInst.mInterfaceType;
|
auto ifaceInst = ifaceTypeInst.mInterfaceType;
|
||||||
int startIdx = ifaceTypeInst.mStartInterfaceTableIdx;
|
int startIdx = ifaceTypeInst.mStartInterfaceTableIdx;
|
||||||
int iMethodCount = (int)ifaceInst->mMethodInstanceGroups.size();
|
int iMethodCount = (int)ifaceInst->mMethodInstanceGroups.size();
|
||||||
|
@ -3978,7 +3978,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
||||||
{
|
{
|
||||||
bool searchFailed = false;
|
bool searchFailed = false;
|
||||||
for (auto& checkIFaceTypeInst : typeInstance->mInterfaces)
|
for (auto& checkIFaceTypeInst : typeInstance->mInterfaces)
|
||||||
{
|
{
|
||||||
auto checkIFaceInst = checkIFaceTypeInst.mInterfaceType;
|
auto checkIFaceInst = checkIFaceTypeInst.mInterfaceType;
|
||||||
int checkStartIdx = checkIFaceTypeInst.mStartInterfaceTableIdx;
|
int checkStartIdx = checkIFaceTypeInst.mStartInterfaceTableIdx;
|
||||||
int checkIMethodCount = (int)checkIFaceInst->mMethodInstanceGroups.size();
|
int checkIMethodCount = (int)checkIFaceInst->mMethodInstanceGroups.size();
|
||||||
|
@ -4067,8 +4067,9 @@ 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)
|
||||||
|
@ -4094,16 +4095,16 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
||||||
if ((ifaceMethodInst->mVirtualTableIdx != -1) && (ifaceMethodInst->mReturnType->IsInterface()))
|
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);
|
mCompiler->mPassInstance->MoreInfo("Declare the interface method as 'concrete' to allow matching concrete return values", ifaceMethodInst->mMethodDef->GetMethodDeclaration()->mVirtualSpecifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear out the entry
|
// Clear out the entry
|
||||||
*matchedMethodRef = BfMethodRef();
|
*matchedMethodRef = BfMethodRef();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ambiguityContext.Finish();
|
ambiguityContext.Finish();
|
||||||
CheckAddFailType();
|
CheckAddFailType();
|
||||||
|
@ -6178,9 +6179,7 @@ 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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue