mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-18 16:10:26 +02:00
Added fixit for adding enum cases
This commit is contained in:
parent
75afbd4a3e
commit
7a5dd90cff
7 changed files with 247 additions and 147 deletions
|
@ -3651,7 +3651,7 @@ namespace IDE
|
||||||
[IDECommand]
|
[IDECommand]
|
||||||
public void Cmd_ReformatDocument()
|
public void Cmd_ReformatDocument()
|
||||||
{
|
{
|
||||||
var sourceViewPanel = GetActiveSourceViewPanel();
|
var sourceViewPanel = GetActiveSourceViewPanel(true);
|
||||||
if (sourceViewPanel != null)
|
if (sourceViewPanel != null)
|
||||||
sourceViewPanel.ReformatDocument();
|
sourceViewPanel.ReformatDocument();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1325,7 +1325,6 @@ namespace IDE
|
||||||
|
|
||||||
public ~this()
|
public ~this()
|
||||||
{
|
{
|
||||||
NOP!();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetProjectRelPath(String fullPath, String outRelPath)
|
public void GetProjectRelPath(String fullPath, String outRelPath)
|
||||||
|
|
|
@ -237,11 +237,6 @@ namespace IDE.ui
|
||||||
|
|
||||||
//Debug.WriteLine("Init {} {} {} {}", this, mIsInitted, mOwnsWindow, mAutoComplete);
|
//Debug.WriteLine("Init {} {} {} {}", this, mIsInitted, mOwnsWindow, mAutoComplete);
|
||||||
|
|
||||||
if (WidgetWindow.sOnMouseDown.Count > 0)
|
|
||||||
{
|
|
||||||
NOP!();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mOwnsWindow)
|
if (mOwnsWindow)
|
||||||
{
|
{
|
||||||
WidgetWindow.sOnWindowLostFocus.Add(new => LostFocusHandler);
|
WidgetWindow.sOnWindowLostFocus.Add(new => LostFocusHandler);
|
||||||
|
@ -369,7 +364,6 @@ namespace IDE.ui
|
||||||
|
|
||||||
public ~this()
|
public ~this()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(Graphics g)
|
public void Draw(Graphics g)
|
||||||
|
@ -2187,6 +2181,12 @@ namespace IDE.ui
|
||||||
SourceViewPanel sourceViewPanel = IDEApp.sApp.ShowSourceFile(fixitFileName);
|
SourceViewPanel sourceViewPanel = IDEApp.sApp.ShowSourceFile(fixitFileName);
|
||||||
if (sourceViewPanel != null)
|
if (sourceViewPanel != null)
|
||||||
{
|
{
|
||||||
|
if (sourceViewPanel.IsReadOnly)
|
||||||
|
{
|
||||||
|
gApp.Fail(scope String()..AppendF("The selected fixit cannot be applied to locked file '{}'", sourceViewPanel.mFilePath));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|
|
@ -1326,15 +1326,6 @@ namespace IDE.ui
|
||||||
|
|
||||||
int alignColumn = GetLineEndColumn(lineAndColumn.mLine, isBlock, true, true);
|
int alignColumn = GetLineEndColumn(lineAndColumn.mLine, isBlock, true, true);
|
||||||
|
|
||||||
if ((useString.StartsWith("case ")) ||
|
|
||||||
(useString.StartsWith("when ")) ||
|
|
||||||
(useString.StartsWith("default:")) ||
|
|
||||||
(useString.StartsWith("default ")))
|
|
||||||
{
|
|
||||||
//CursorLineAndColumn = LineAndColumn(lineAndColumn.mLine, alignColumn - tabSpaceCount);
|
|
||||||
//alignColumn--;
|
|
||||||
}
|
|
||||||
|
|
||||||
String linePrefix = scope String('\t', alignColumn / tabSpaceCount);
|
String linePrefix = scope String('\t', alignColumn / tabSpaceCount);
|
||||||
CursorLineAndColumn = LineAndColumn(lineAndColumn.mLine, alignColumn);
|
CursorLineAndColumn = LineAndColumn(lineAndColumn.mLine, alignColumn);
|
||||||
|
|
||||||
|
@ -1342,10 +1333,11 @@ namespace IDE.ui
|
||||||
if (useString.StartsWith("{"))
|
if (useString.StartsWith("{"))
|
||||||
isFullSwitch = true;
|
isFullSwitch = true;
|
||||||
|
|
||||||
if ((useString.StartsWith("case ")) ||
|
if ((useString.Contains(':')) &&
|
||||||
(useString.StartsWith("when ")) ||
|
((useString.StartsWith("case ")) ||
|
||||||
(useString.StartsWith("default:")) ||
|
(useString.StartsWith("when ")) ||
|
||||||
(useString.StartsWith("default ")))
|
(useString.StartsWith("default:")) ||
|
||||||
|
(useString.StartsWith("default "))))
|
||||||
{
|
{
|
||||||
CursorLineAndColumn = LineAndColumn(lineAndColumn.mLine, Math.Max(0, alignColumn - tabSpaceCount));
|
CursorLineAndColumn = LineAndColumn(lineAndColumn.mLine, Math.Max(0, alignColumn - tabSpaceCount));
|
||||||
|
|
||||||
|
@ -2110,6 +2102,7 @@ namespace IDE.ui
|
||||||
bool hasEmptyAutocompleteReplace = true;
|
bool hasEmptyAutocompleteReplace = true;
|
||||||
if (mAutoComplete != null)
|
if (mAutoComplete != null)
|
||||||
hasEmptyAutocompleteReplace = mAutoComplete.mInsertEndIdx == -1;
|
hasEmptyAutocompleteReplace = mAutoComplete.mInsertEndIdx == -1;
|
||||||
|
bool didAutoComplete = false;
|
||||||
|
|
||||||
bool isEndingChar = (keyChar >= (char8)32) && !keyChar.IsLetterOrDigit && (keyChar != '_') && (keyChar != '~') && (keyChar != '=') && (keyChar != '!') && (keyChar != ':');
|
bool isEndingChar = (keyChar >= (char8)32) && !keyChar.IsLetterOrDigit && (keyChar != '_') && (keyChar != '~') && (keyChar != '=') && (keyChar != '!') && (keyChar != ':');
|
||||||
|
|
||||||
|
@ -2203,6 +2196,7 @@ namespace IDE.ui
|
||||||
{
|
{
|
||||||
if (IsCursorVisible(false))
|
if (IsCursorVisible(false))
|
||||||
mOnGenerateAutocomplete('\0', default);
|
mOnGenerateAutocomplete('\0', default);
|
||||||
|
didAutoComplete = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2602,25 +2596,13 @@ namespace IDE.ui
|
||||||
if (mAutoComplete != null)
|
if (mAutoComplete != null)
|
||||||
{
|
{
|
||||||
mAutoComplete.UpdateAsyncInfo();
|
mAutoComplete.UpdateAsyncInfo();
|
||||||
|
|
||||||
/*if (mAutoComplete != null)
|
|
||||||
{
|
|
||||||
String filter = scope String();
|
|
||||||
mAutoComplete.GetFilter(filter);
|
|
||||||
if ((filter.Length < mAutoComplete.mInfoFilter.Length) || (mAutoComplete.mInfoFilter.Length == 1))
|
|
||||||
{
|
|
||||||
needsFreshAutoComplete = true;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
needsFreshAutoComplete = true;
|
needsFreshAutoComplete = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needsFreshAutoComplete)
|
if ((needsFreshAutoComplete) && (!didAutoComplete))
|
||||||
{
|
{
|
||||||
//Profiler.StartSampling();
|
|
||||||
if (IsCursorVisible(false))
|
if (IsCursorVisible(false))
|
||||||
mOnGenerateAutocomplete(keyChar, isHighPri ? .HighPriority : default);
|
mOnGenerateAutocomplete(keyChar, isHighPri ? .HighPriority : default);
|
||||||
//Profiler.StopSampling();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mData.mCurTextVersionId != startRevision)
|
else if (mData.mCurTextVersionId != startRevision)
|
||||||
|
|
|
@ -2645,4 +2645,211 @@ void BfAutoComplete::FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType,
|
||||||
}
|
}
|
||||||
|
|
||||||
AddEntry(AutoCompleteEntry("fixit", StrFormat("Create field '%s' in '%s'\taddField|%s|%d||%s", fieldName.c_str(), fullName.c_str(), parser->mFileName.c_str(), fileLoc, fieldStr.c_str()).c_str()));
|
AddEntry(AutoCompleteEntry("fixit", StrFormat("Create field '%s' in '%s'\taddField|%s|%d||%s", fieldName.c_str(), fullName.c_str(), parser->mFileName.c_str(), fileLoc, fieldStr.c_str()).c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BfAutoComplete::FixitAddCase(BfTypeInstance* typeInst, const StringImpl& caseName, const BfTypeVector& fieldTypes)
|
||||||
|
{
|
||||||
|
if (typeInst == mModule->mContext->mBfObjectType)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto parser = typeInst->mTypeDef->mSource->ToParser();
|
||||||
|
if (parser == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
String fullName = typeInst->mTypeDef->mFullName.ToString();
|
||||||
|
String fieldStr;
|
||||||
|
|
||||||
|
int fileLoc = typeInst->mTypeDef->mTypeDeclaration->GetSrcEnd();
|
||||||
|
|
||||||
|
if (auto defineBlock = BfNodeDynCast<BfBlock>(typeInst->mTypeDef->mTypeDeclaration->mDefineNode))
|
||||||
|
fileLoc = BfFixitFinder::FindLineStartAfter(defineBlock->mOpenBrace);
|
||||||
|
if (!typeInst->mTypeDef->mFields.empty())
|
||||||
|
{
|
||||||
|
auto fieldDecl = typeInst->mTypeDef->mFields.back()->mFieldDeclaration;
|
||||||
|
if (fieldDecl != NULL)
|
||||||
|
{
|
||||||
|
fileLoc = BfFixitFinder::FindLineStartAfter(fieldDecl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSimpleCase = false;
|
||||||
|
if (!typeInst->mTypeDef->mFields.IsEmpty())
|
||||||
|
{
|
||||||
|
if (auto block = BfNodeDynCast<BfBlock>(typeInst->mTypeDef->mTypeDeclaration->mDefineNode))
|
||||||
|
{
|
||||||
|
bool endsInComma = false;
|
||||||
|
|
||||||
|
if (!block->mChildArr.IsEmpty())
|
||||||
|
{
|
||||||
|
auto lastNode = block->mChildArr.back();
|
||||||
|
if (auto tokenNode = BfNodeDynCast<BfTokenNode>(lastNode))
|
||||||
|
{
|
||||||
|
if (tokenNode->mToken == BfToken_Comma)
|
||||||
|
{
|
||||||
|
isSimpleCase = true;
|
||||||
|
endsInComma = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (auto enumEntryDecl = BfNodeDynCast<BfEnumEntryDeclaration>(lastNode))
|
||||||
|
{
|
||||||
|
isSimpleCase = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSimpleCase)
|
||||||
|
{
|
||||||
|
if (endsInComma)
|
||||||
|
{
|
||||||
|
fieldStr += "|";
|
||||||
|
fieldStr += caseName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto fieldDef = typeInst->mTypeDef->mFields.back();
|
||||||
|
fileLoc = fieldDef->mFieldDeclaration->GetSrcEnd();
|
||||||
|
fieldStr += ",\r";
|
||||||
|
fieldStr += caseName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isSimpleCase)
|
||||||
|
{
|
||||||
|
fieldStr += "|case ";
|
||||||
|
fieldStr += caseName;
|
||||||
|
|
||||||
|
if (!fieldTypes.IsEmpty())
|
||||||
|
{
|
||||||
|
fieldStr += "(";
|
||||||
|
FixitGetParamString(fieldTypes, fieldStr);
|
||||||
|
fieldStr += ")";
|
||||||
|
}
|
||||||
|
fieldStr += ";";
|
||||||
|
}
|
||||||
|
|
||||||
|
AddEntry(AutoCompleteEntry("fixit", StrFormat("Create case '%s' in '%s'\taddField|%s|%d|%s", caseName.c_str(), fullName.c_str(), parser->mFileName.c_str(), fileLoc, fieldStr.c_str()).c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BfAutoComplete::FixitGetParamString(const BfTypeVector& paramTypes, StringImpl& outStr)
|
||||||
|
{
|
||||||
|
std::set<String> usedNames;
|
||||||
|
|
||||||
|
for (int argIdx = 0; argIdx < (int)paramTypes.size(); argIdx++)
|
||||||
|
{
|
||||||
|
if (argIdx > 0)
|
||||||
|
outStr += ", ";
|
||||||
|
BfType* paramType = paramTypes[argIdx];
|
||||||
|
String checkName = "param";
|
||||||
|
if (paramType != NULL)
|
||||||
|
{
|
||||||
|
bool isOut = false;
|
||||||
|
bool isArr = false;
|
||||||
|
|
||||||
|
BfType* checkType = paramType;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if ((checkType->IsArray()) || (checkType->IsSizedArray()))
|
||||||
|
{
|
||||||
|
isArr = true;
|
||||||
|
checkType = checkType->GetUnderlyingType();
|
||||||
|
}
|
||||||
|
else if (checkType->IsRef())
|
||||||
|
{
|
||||||
|
BfRefType* refType = (BfRefType*)checkType;
|
||||||
|
if (refType->mRefKind == BfRefType::RefKind_Out)
|
||||||
|
isOut = true;
|
||||||
|
checkType = refType->GetUnderlyingType();
|
||||||
|
}
|
||||||
|
else if (checkType->IsTypeInstance())
|
||||||
|
{
|
||||||
|
BfTypeInstance* typeInst = (BfTypeInstance*)checkType;
|
||||||
|
checkName = typeInst->mTypeDef->mName->ToString();
|
||||||
|
if (checkName == "String")
|
||||||
|
checkName = "Str";
|
||||||
|
if (checkName == "Object")
|
||||||
|
checkName = "Obj";
|
||||||
|
if (isOut)
|
||||||
|
checkName = "out" + checkName;
|
||||||
|
else if (isupper(checkName[0]))
|
||||||
|
checkName[0] = tolower(checkName[0]);
|
||||||
|
if (isArr)
|
||||||
|
checkName += "Arr";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
outStr += mModule->TypeToString(paramType, BfTypeNameFlag_ReduceName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
checkName = "param";
|
||||||
|
outStr += "Object";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < 10; i++)
|
||||||
|
{
|
||||||
|
String lookupName = checkName;
|
||||||
|
if (i > 1)
|
||||||
|
lookupName += StrFormat("%d", i);
|
||||||
|
if (usedNames.insert(lookupName).second)
|
||||||
|
{
|
||||||
|
outStr += " " + lookupName;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BfAutoComplete::FixitAddMethod(BfTypeInstance* typeInst, const StringImpl& methodName, BfType* returnType, const BfTypeVector& paramTypes, bool wantStatic)
|
||||||
|
{
|
||||||
|
if ((typeInst->IsEnum()) && (returnType == typeInst) && (wantStatic))
|
||||||
|
{
|
||||||
|
FixitAddCase(typeInst, methodName, paramTypes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((typeInst->mTypeDef->mSource != NULL) && (typeInst != mModule->mContext->mBfObjectType))
|
||||||
|
{
|
||||||
|
auto parser = typeInst->mTypeDef->mSource->ToParser();
|
||||||
|
if (parser != NULL)
|
||||||
|
{
|
||||||
|
String fullName = typeInst->mTypeDef->mFullName.ToString();
|
||||||
|
String methodStr;
|
||||||
|
|
||||||
|
if (typeInst == mModule->mCurTypeInstance)
|
||||||
|
{
|
||||||
|
// Implicitly private
|
||||||
|
}
|
||||||
|
else if (mModule->TypeIsSubTypeOf(mModule->mCurTypeInstance, typeInst))
|
||||||
|
{
|
||||||
|
methodStr += "protected ";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
methodStr += "public ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wantStatic)
|
||||||
|
methodStr += "static ";
|
||||||
|
|
||||||
|
if (returnType != NULL)
|
||||||
|
methodStr += mModule->TypeToString(returnType, BfTypeNameFlag_ReduceName);
|
||||||
|
else
|
||||||
|
methodStr += "void";
|
||||||
|
|
||||||
|
methodStr += " " + methodName + "(";
|
||||||
|
|
||||||
|
FixitGetParamString(paramTypes, methodStr);
|
||||||
|
|
||||||
|
int fileLoc = typeInst->mTypeDef->mTypeDeclaration->GetSrcEnd();
|
||||||
|
if (auto defineBlock = BfNodeDynCast<BfBlock>(typeInst->mTypeDef->mTypeDeclaration->mDefineNode))
|
||||||
|
fileLoc = defineBlock->mCloseBrace->GetSrcStart();
|
||||||
|
|
||||||
|
methodStr += ")";
|
||||||
|
AddEntry(AutoCompleteEntry("fixit", StrFormat("Create method '%s' in '%s'\taddMethod|%s|%d|||%s|{||}", methodName.c_str(), fullName.c_str(), parser->mFileName.c_str(), fileLoc, methodStr.c_str()).c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -219,6 +219,7 @@ public:
|
||||||
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);
|
bool GetMethodInfo(BfMethodInstance* methodInst, StringImpl* methodName, StringImpl* insertString, bool isExplicitInterface);
|
||||||
|
void FixitGetParamString(const BfTypeVector& paramTypes, StringImpl& outStr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BfAutoComplete(BfResolveType resolveType = BfResolveType_Autocomplete);
|
BfAutoComplete(BfResolveType resolveType = BfResolveType_Autocomplete);
|
||||||
|
@ -248,7 +249,9 @@ public:
|
||||||
bool CheckFixit(BfAstNode* node);
|
bool CheckFixit(BfAstNode* node);
|
||||||
void ChcekInterfaceFixit(BfTypeInstance* typeInstance, 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);
|
||||||
|
void FixitAddCase(BfTypeInstance * typeInst, const StringImpl & caseName, const BfTypeVector & fieldTypes);
|
||||||
|
void FixitAddMethod(BfTypeInstance* typeInst, const StringImpl& methodName, BfType* returnType, const BfTypeVector& paramTypes, bool wantStatic);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4802,7 +4802,7 @@ void BfExprEvaluator::FinishDeferredEvals(SizedArrayImpl<BfResolvedArg>& argValu
|
||||||
{
|
{
|
||||||
for (int argIdx = 0; argIdx < argValues.size(); argIdx++)
|
for (int argIdx = 0; argIdx < argValues.size(); argIdx++)
|
||||||
{
|
{
|
||||||
auto argValue = argValues[argIdx].mTypedValue;
|
auto& argValue = argValues[argIdx].mTypedValue;
|
||||||
if ((argValues[argIdx].mArgFlags & (BfArgFlag_DelegateBindAttempt | BfArgFlag_LambdaBindAttempt | BfArgFlag_UnqualifiedDotAttempt | BfArgFlag_DeferredEval)) != 0)
|
if ((argValues[argIdx].mArgFlags & (BfArgFlag_DelegateBindAttempt | BfArgFlag_LambdaBindAttempt | BfArgFlag_UnqualifiedDotAttempt | BfArgFlag_DeferredEval)) != 0)
|
||||||
{
|
{
|
||||||
if (!argValue)
|
if (!argValue)
|
||||||
|
@ -6661,129 +6661,31 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
||||||
|
|
||||||
if (methodDef == NULL)
|
if (methodDef == NULL)
|
||||||
{
|
{
|
||||||
|
FinishDeferredEvals(argValues.mResolvedArgs);
|
||||||
auto compiler = mModule->mCompiler;
|
auto compiler = mModule->mCompiler;
|
||||||
if ((compiler->IsAutocomplete()) && (compiler->mResolvePassData->mAutoComplete->CheckFixit(targetSrc)))
|
if ((compiler->IsAutocomplete()) && (compiler->mResolvePassData->mAutoComplete->CheckFixit(targetSrc)))
|
||||||
{
|
{
|
||||||
mModule->CheckTypeRefFixit(targetSrc);
|
mModule->CheckTypeRefFixit(targetSrc);
|
||||||
|
|
||||||
bool wantStatic = !target.mValue;
|
bool wantStatic = !target.mValue;
|
||||||
if ((targetType == NULL) && (allowImplicitThis))
|
if ((targetType == NULL) && (allowImplicitThis))
|
||||||
{
|
{
|
||||||
targetType = mModule->mCurTypeInstance;
|
targetType = mModule->mCurTypeInstance;
|
||||||
if (mModule->mCurMethodInstance != NULL)
|
if (mModule->mCurMethodInstance != NULL)
|
||||||
wantStatic = mModule->mCurMethodInstance->mMethodDef->mIsStatic;
|
wantStatic = mModule->mCurMethodInstance->mMethodDef->mIsStatic;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetType != NULL)
|
if (targetType != NULL)
|
||||||
{
|
{
|
||||||
auto typeInst = targetType->ToTypeInstance();
|
auto typeInst = targetType->ToTypeInstance();
|
||||||
if ((typeInst->mTypeDef->mSource != NULL) && (typeInst != mModule->mContext->mBfObjectType))
|
|
||||||
{
|
|
||||||
auto parser = typeInst->mTypeDef->mSource->ToParser();
|
|
||||||
if (parser != NULL)
|
|
||||||
{
|
|
||||||
String fullName = typeInst->mTypeDef->mFullName.ToString();
|
|
||||||
String methodStr;
|
|
||||||
|
|
||||||
if (typeInst == mModule->mCurTypeInstance)
|
BfTypeVector paramTypes;
|
||||||
{
|
for (int argIdx = 0; argIdx < (int)argValues.mResolvedArgs.size(); argIdx++)
|
||||||
// Implicitly private
|
{
|
||||||
}
|
auto& resolvedArg = argValues.mResolvedArgs[argIdx];
|
||||||
else if (mModule->TypeIsSubTypeOf(mModule->mCurTypeInstance, typeInst))
|
paramTypes.Add(resolvedArg.mTypedValue.mType);
|
||||||
{
|
|
||||||
methodStr += "protected ";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
methodStr += "public ";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wantStatic)
|
|
||||||
methodStr += "static ";
|
|
||||||
|
|
||||||
if (mExpectingType != NULL)
|
|
||||||
methodStr += mModule->TypeToString(mExpectingType, BfTypeNameFlag_ReduceName);
|
|
||||||
else
|
|
||||||
methodStr += "void";
|
|
||||||
|
|
||||||
methodStr += " " + methodName + "(";
|
|
||||||
|
|
||||||
std::set<String> usedNames;
|
|
||||||
|
|
||||||
for (int argIdx = 0; argIdx < (int)argValues.mResolvedArgs.size(); argIdx++)
|
|
||||||
{
|
|
||||||
if (argIdx > 0)
|
|
||||||
methodStr += ", ";
|
|
||||||
auto& resolvedArg = argValues.mResolvedArgs[argIdx];
|
|
||||||
String checkName = "param";
|
|
||||||
if (resolvedArg.mTypedValue.mType != NULL)
|
|
||||||
{
|
|
||||||
bool isOut = false;
|
|
||||||
bool isArr = false;
|
|
||||||
|
|
||||||
BfType* checkType = resolvedArg.mTypedValue.mType;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if ((checkType->IsArray()) || (checkType->IsSizedArray()))
|
|
||||||
{
|
|
||||||
isArr = true;
|
|
||||||
checkType = checkType->GetUnderlyingType();
|
|
||||||
}
|
|
||||||
else if (checkType->IsRef())
|
|
||||||
{
|
|
||||||
BfRefType* refType = (BfRefType*)checkType;
|
|
||||||
if (refType->mRefKind == BfRefType::RefKind_Out)
|
|
||||||
isOut = true;
|
|
||||||
checkType = refType->GetUnderlyingType();
|
|
||||||
}
|
|
||||||
else if (checkType->IsTypeInstance())
|
|
||||||
{
|
|
||||||
BfTypeInstance* typeInst = (BfTypeInstance*)checkType;
|
|
||||||
checkName = typeInst->mTypeDef->mName->ToString();
|
|
||||||
if (checkName == "String")
|
|
||||||
checkName = "Str";
|
|
||||||
if (checkName == "Object")
|
|
||||||
checkName = "Obj";
|
|
||||||
if (isOut)
|
|
||||||
checkName = "out" + checkName;
|
|
||||||
else if (isupper(checkName[0]))
|
|
||||||
checkName[0] = tolower(checkName[0]);
|
|
||||||
if (isArr)
|
|
||||||
checkName += "Arr";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
methodStr += mModule->TypeToString(resolvedArg.mTypedValue.mType, BfTypeNameFlag_ReduceName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
checkName = "param";
|
|
||||||
methodStr += "Object";
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 1; i < 10; i++)
|
|
||||||
{
|
|
||||||
String lookupName = checkName;
|
|
||||||
if (i > 1)
|
|
||||||
lookupName += StrFormat("%d", i);
|
|
||||||
if (usedNames.insert(lookupName).second)
|
|
||||||
{
|
|
||||||
methodStr += " " + lookupName;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int fileLoc = typeInst->mTypeDef->mTypeDeclaration->GetSrcEnd();
|
|
||||||
if (auto defineBlock = BfNodeDynCast<BfBlock>(typeInst->mTypeDef->mTypeDeclaration->mDefineNode))
|
|
||||||
fileLoc = defineBlock->mCloseBrace->GetSrcStart();
|
|
||||||
|
|
||||||
methodStr += ")";
|
|
||||||
compiler->mResolvePassData->mAutoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Create method '%s' in '%s'\taddMethod|%s|%d|||%s|{||}", methodName.c_str(), fullName.c_str(), parser->mFileName.c_str(), fileLoc, methodStr.c_str()).c_str()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
autoComplete->FixitAddMethod(typeInst, methodName, mExpectingType, paramTypes, wantStatic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6794,8 +6696,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
||||||
else if (target.mType != NULL)
|
else if (target.mType != NULL)
|
||||||
mModule->Fail(StrFormat("Method '%s' does not exist in type '%s'", methodName.c_str(), mModule->TypeToString(target.mType).c_str()), targetSrc);
|
mModule->Fail(StrFormat("Method '%s' does not exist in type '%s'", methodName.c_str(), mModule->TypeToString(target.mType).c_str()), targetSrc);
|
||||||
else
|
else
|
||||||
mModule->Fail(StrFormat("Method '%s' does not exist", methodName.c_str()), targetSrc);
|
mModule->Fail(StrFormat("Method '%s' does not exist", methodName.c_str()), targetSrc);
|
||||||
FinishDeferredEvals(argValues.mResolvedArgs);
|
|
||||||
return BfTypedValue();
|
return BfTypedValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15902,6 +15803,14 @@ void BfExprEvaluator::DoMemberReference(BfMemberReferenceExpression* memberRefEx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((memberRefExpr->mTarget == NULL) && (expectingTypeInst != NULL) && (autoComplete != NULL))
|
||||||
|
{
|
||||||
|
if (autoComplete->CheckFixit(memberRefExpr->mMemberName))
|
||||||
|
{
|
||||||
|
autoComplete->FixitAddCase(expectingTypeInst, memberRefExpr->mMemberName->ToString(), BfTypeVector());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mResult.mType == NULL)
|
if (mResult.mType == NULL)
|
||||||
mModule->Fail("Unable to find member", nameRefNode);
|
mModule->Fail("Unable to find member", nameRefNode);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue