mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-14 14:24:10 +02:00
Fixed autocomplete issues with nested calls
This commit is contained in:
parent
e1656865bb
commit
f10551e6f8
5 changed files with 70 additions and 41 deletions
|
@ -1794,18 +1794,9 @@ void BfAutoComplete::CheckInvocation(BfAstNode* invocationNode, BfTokenNode* ope
|
||||||
if (doCapture)
|
if (doCapture)
|
||||||
{
|
{
|
||||||
mIsCapturingMethodMatchInfo = true;
|
mIsCapturingMethodMatchInfo = true;
|
||||||
if (mMethodMatchInfo == NULL)
|
|
||||||
mMethodMatchInfo = new MethodMatchInfo();
|
delete mMethodMatchInfo;
|
||||||
else
|
mMethodMatchInfo = new MethodMatchInfo();
|
||||||
{
|
|
||||||
if (wasCapturingMethodMatchInfo)
|
|
||||||
{
|
|
||||||
// We're actually in an inner invocation now
|
|
||||||
delete mMethodMatchInfo;
|
|
||||||
mMethodMatchInfo = new MethodMatchInfo();
|
|
||||||
mMethodMatchInfo->mSrcPositions.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mMethodMatchInfo->mInvocationSrcIdx = target->GetSrcStart();
|
mMethodMatchInfo->mInvocationSrcIdx = target->GetSrcStart();
|
||||||
mMethodMatchInfo->mCurMethodInstance = mModule->mCurMethodInstance;
|
mMethodMatchInfo->mCurMethodInstance = mModule->mCurMethodInstance;
|
||||||
|
|
|
@ -140,8 +140,8 @@ public:
|
||||||
BfMethodInstance* mCurMethodInstance;
|
BfMethodInstance* mCurMethodInstance;
|
||||||
Array<MethodMatchEntry> mInstanceList;
|
Array<MethodMatchEntry> mInstanceList;
|
||||||
int mInvocationSrcIdx;
|
int mInvocationSrcIdx;
|
||||||
int mBestIdx;
|
int mBestIdx;
|
||||||
int mPrevBestIdx;
|
int mPrevBestIdx;
|
||||||
bool mHadExactMatch;
|
bool mHadExactMatch;
|
||||||
int mMostParamsMatched;
|
int mMostParamsMatched;
|
||||||
Array<int> mSrcPositions; // start, commas, end
|
Array<int> mSrcPositions; // start, commas, end
|
||||||
|
@ -152,8 +152,8 @@ public:
|
||||||
mInvocationSrcIdx = -1;
|
mInvocationSrcIdx = -1;
|
||||||
mCurTypeInstance = NULL;
|
mCurTypeInstance = NULL;
|
||||||
mCurMethodInstance = NULL;
|
mCurMethodInstance = NULL;
|
||||||
mBestIdx = 0;
|
mBestIdx = 0;
|
||||||
mPrevBestIdx = -1;
|
mPrevBestIdx = -1;
|
||||||
mHadExactMatch = false;
|
mHadExactMatch = false;
|
||||||
mMostParamsMatched = 0;
|
mMostParamsMatched = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -833,7 +833,7 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
|
||||||
RETURN_RESULTS;
|
RETURN_RESULTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType)
|
BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType, BfTypeVector* genericArgumentsSubstitute)
|
||||||
{
|
{
|
||||||
BfTypedValue argTypedValue = resolvedArg.mTypedValue;
|
BfTypedValue argTypedValue = resolvedArg.mTypedValue;
|
||||||
if ((resolvedArg.mArgFlags & BfArgFlag_DelegateBindAttempt) != 0)
|
if ((resolvedArg.mArgFlags & BfArgFlag_DelegateBindAttempt) != 0)
|
||||||
|
@ -909,9 +909,8 @@ BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, B
|
||||||
if ((resolvedArg.mExpectedType != checkType) || (resolvedArg.mExpectedType == NULL)) // Did our last check match for this type?
|
if ((resolvedArg.mExpectedType != checkType) || (resolvedArg.mExpectedType == NULL)) // Did our last check match for this type?
|
||||||
{
|
{
|
||||||
SetAndRestoreValue<bool> prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
|
SetAndRestoreValue<bool> prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
|
||||||
SetAndRestoreValue<bool> prevIgnoreError(mModule->mIgnoreErrors, true);
|
SetAndRestoreValue<bool> prevIgnoreError(mModule->mIgnoreErrors, true);
|
||||||
//SetAndRestoreValue<bool> prevNoBind(mModule->mCurMethodState->mNoBind, true);
|
|
||||||
|
|
||||||
bool prevNoBind = false;
|
bool prevNoBind = false;
|
||||||
if (mModule->mCurMethodState != NULL)
|
if (mModule->mCurMethodState != NULL)
|
||||||
{
|
{
|
||||||
|
@ -921,12 +920,28 @@ BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, B
|
||||||
|
|
||||||
auto prevBlock = mModule->mBfIRBuilder->GetInsertBlock();
|
auto prevBlock = mModule->mBfIRBuilder->GetInsertBlock();
|
||||||
|
|
||||||
BfExprEvaluator exprEvaluator(mModule);
|
|
||||||
exprEvaluator.mExpectingType = checkType;
|
BfExprEvaluator exprEvaluator(mModule);
|
||||||
exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowIntUnknown);
|
exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowIntUnknown | BfEvalExprFlags_NoAutoComplete);
|
||||||
if ((resolvedArg.mArgFlags & BfArgFlag_ParamsExpr) != 0)
|
if ((resolvedArg.mArgFlags & BfArgFlag_ParamsExpr) != 0)
|
||||||
exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowParamsExpr);
|
exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowParamsExpr);
|
||||||
exprEvaluator.Evaluate(resolvedArg.mExpression);
|
|
||||||
|
auto expectType = checkType;
|
||||||
|
if (expectType != NULL)
|
||||||
|
{
|
||||||
|
if (expectType->IsRef())
|
||||||
|
{
|
||||||
|
auto refType = (BfRefType*)expectType;
|
||||||
|
expectType = refType->mElementType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (genericArgumentsSubstitute != NULL)
|
||||||
|
expectType = mModule->ResolveGenericType(expectType, *genericArgumentsSubstitute, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
exprEvaluator.mExpectingType = expectType;
|
||||||
|
|
||||||
|
exprEvaluator.Evaluate(resolvedArg.mExpression);
|
||||||
argTypedValue = exprEvaluator.GetResult();
|
argTypedValue = exprEvaluator.GetResult();
|
||||||
|
|
||||||
if (mModule->mCurMethodState != NULL)
|
if (mModule->mCurMethodState != NULL)
|
||||||
|
@ -1046,6 +1061,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
|
||||||
|
|
||||||
BfTypeVector* genericArgumentsSubstitute = NULL;
|
BfTypeVector* genericArgumentsSubstitute = NULL;
|
||||||
int argIdx = 0;
|
int argIdx = 0;
|
||||||
|
int argMatchCount = 0;
|
||||||
|
|
||||||
bool needInferGenericParams = (checkMethod->mGenericParams.size() != 0) && (!mHadExplicitGenericArguments);
|
bool needInferGenericParams = (checkMethod->mGenericParams.size() != 0) && (!mHadExplicitGenericArguments);
|
||||||
int paramIdx = 0;
|
int paramIdx = 0;
|
||||||
|
@ -1140,7 +1156,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
|
||||||
|
|
||||||
if (wantType->IsUnspecializedType())
|
if (wantType->IsUnspecializedType())
|
||||||
{
|
{
|
||||||
BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], checkType);
|
BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], checkType, genericArgumentsSubstitute);
|
||||||
if (!argTypedValue.IsUntypedValue())
|
if (!argTypedValue.IsUntypedValue())
|
||||||
{
|
{
|
||||||
auto type = argTypedValue.mType;
|
auto type = argTypedValue.mType;
|
||||||
|
@ -1209,7 +1225,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
|
||||||
if (paramIdx >= (int) mArguments.size())
|
if (paramIdx >= (int) mArguments.size())
|
||||||
break; // No params
|
break; // No params
|
||||||
|
|
||||||
BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], NULL);
|
BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], NULL, genericArgumentsSubstitute);
|
||||||
if (!argTypedValue)
|
if (!argTypedValue)
|
||||||
goto NoMatch;
|
goto NoMatch;
|
||||||
|
|
||||||
|
@ -1224,7 +1240,8 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
|
||||||
if ((argTypedValue.IsUntypedValue()) || (mModule->CanImplicitlyCast(argTypedValue, paramsArrayType)))
|
if ((argTypedValue.IsUntypedValue()) || (mModule->CanImplicitlyCast(argTypedValue, paramsArrayType)))
|
||||||
{
|
{
|
||||||
argIdx++;
|
argIdx++;
|
||||||
paramIdx++;
|
argMatchCount++;
|
||||||
|
paramIdx++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1238,12 +1255,13 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
|
||||||
|
|
||||||
while (argIdx < (int)mArguments.size())
|
while (argIdx < (int)mArguments.size())
|
||||||
{
|
{
|
||||||
argTypedValue = ResolveArgTypedValue(mArguments[argIdx], paramsElementType);
|
argTypedValue = ResolveArgTypedValue(mArguments[argIdx], paramsElementType, genericArgumentsSubstitute);
|
||||||
if (!argTypedValue.HasType())
|
if (!argTypedValue.HasType())
|
||||||
goto NoMatch;
|
goto NoMatch;
|
||||||
if (!mModule->CanImplicitlyCast(argTypedValue, paramsElementType))
|
if (!mModule->CanImplicitlyCast(argTypedValue, paramsElementType))
|
||||||
goto NoMatch;
|
goto NoMatch;
|
||||||
argIdx++;
|
argIdx++;
|
||||||
|
argMatchCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1283,7 +1301,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
|
||||||
// We had a 'params' expression but this method didn't have a params slot in this parameter
|
// We had a 'params' expression but this method didn't have a params slot in this parameter
|
||||||
goto NoMatch;
|
goto NoMatch;
|
||||||
}
|
}
|
||||||
BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], wantType);
|
BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], wantType, genericArgumentsSubstitute);
|
||||||
|
|
||||||
if (!argTypedValue.IsUntypedValue())
|
if (!argTypedValue.IsUntypedValue())
|
||||||
{
|
{
|
||||||
|
@ -1297,6 +1315,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
|
||||||
|
|
||||||
paramIdx++;
|
paramIdx++;
|
||||||
argIdx++;
|
argIdx++;
|
||||||
|
argMatchCount++;
|
||||||
|
|
||||||
if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo))
|
if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo))
|
||||||
{
|
{
|
||||||
|
@ -1430,21 +1449,30 @@ NoMatch:
|
||||||
if ((prevParamDiff >= 0) && ((paramDiff < 0) || (prevParamDiff < paramDiff)))
|
if ((prevParamDiff >= 0) && ((paramDiff < 0) || (prevParamDiff < paramDiff)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// We search from the most specific type, so don't prefer a less specific type
|
if (paramDiff == prevParamDiff)
|
||||||
if ((paramDiff == prevParamDiff) && (mBestMethodTypeInstance != typeInstance))
|
{
|
||||||
return false;
|
if (argMatchCount < mBackupArgMatchCount)
|
||||||
|
return false;
|
||||||
|
else if (argMatchCount == mBackupArgMatchCount)
|
||||||
|
{
|
||||||
|
// We search from the most specific type, so don't prefer a less specific type
|
||||||
|
if (mBestMethodTypeInstance != typeInstance)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo))
|
if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo))
|
||||||
{
|
{
|
||||||
auto methodMatchInfo = autoComplete->mMethodMatchInfo;
|
auto methodMatchInfo = autoComplete->mMethodMatchInfo;
|
||||||
if ((methodMatchInfo->mPrevBestIdx == -1) && (!methodMatchInfo->mHadExactMatch))
|
if ((methodMatchInfo->mPrevBestIdx == -1) && (!methodMatchInfo->mHadExactMatch))
|
||||||
{
|
{
|
||||||
methodMatchInfo->mBestIdx = (int)methodMatchInfo->mInstanceList.size() - 1;
|
methodMatchInfo->mBestIdx = (int)methodMatchInfo->mInstanceList.size() - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mBackupMethodDef = checkMethod;
|
mBackupMethodDef = checkMethod;
|
||||||
|
mBackupArgMatchCount = argMatchCount;
|
||||||
// Lie temporarily to store at least one candidate (but mBestMethodDef is still NULL)
|
// Lie temporarily to store at least one candidate (but mBestMethodDef is still NULL)
|
||||||
hadMatch = true;
|
hadMatch = true;
|
||||||
}
|
}
|
||||||
|
@ -1950,6 +1978,8 @@ BfAutoComplete* BfExprEvaluator::GetAutoComplete()
|
||||||
{
|
{
|
||||||
if (mModule->mCompiler->mResolvePassData == NULL)
|
if (mModule->mCompiler->mResolvePassData == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if ((mBfEvalExprFlags & BfEvalExprFlags_NoAutoComplete) != 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// For local methods- only process autocomplete on capture phase
|
// For local methods- only process autocomplete on capture phase
|
||||||
if ((mModule->mCurMethodState != NULL) && (mModule->mCurMethodState->mClosureState != NULL) && (!mModule->mCurMethodState->mClosureState->mCapturing))
|
if ((mModule->mCurMethodState != NULL) && (mModule->mCurMethodState->mClosureState != NULL) && (!mModule->mCurMethodState->mClosureState->mCapturing))
|
||||||
|
@ -7826,9 +7856,17 @@ void BfExprEvaluator::Visit(BfDefaultExpression* defaultExpr)
|
||||||
type = mModule->ResolveTypeRef(defaultExpr->mTypeRef);
|
type = mModule->ResolveTypeRef(defaultExpr->mTypeRef);
|
||||||
if (type == NULL)
|
if (type == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
BfDefaultValueKind defaultKind = BfDefaultValueKind_Const;
|
||||||
|
if (type->IsRef())
|
||||||
|
{
|
||||||
|
mModule->Fail(StrFormat("There is no default value for type '%s'", mModule->TypeToString(type).c_str()), defaultExpr);
|
||||||
|
defaultKind = BfDefaultValueKind_Addr;
|
||||||
|
}
|
||||||
|
|
||||||
mModule->ValidateAllocation(type, defaultExpr->mTypeRef);
|
mModule->ValidateAllocation(type, defaultExpr->mTypeRef);
|
||||||
mModule->AddDependency(type, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
|
mModule->AddDependency(type, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
|
||||||
mResult = mModule->GetDefaultTypedValue(type);
|
mResult = mModule->GetDefaultTypedValue(type, true, defaultKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfExprEvaluator::Visit(BfUninitializedExpression* uninitialziedExpr)
|
void BfExprEvaluator::Visit(BfUninitializedExpression* uninitialziedExpr)
|
||||||
|
|
|
@ -142,6 +142,7 @@ public:
|
||||||
|
|
||||||
BfType* mSelfType; // Only when matching interfaces when 'Self' needs to refer back to the implementing type
|
BfType* mSelfType; // Only when matching interfaces when 'Self' needs to refer back to the implementing type
|
||||||
BfMethodDef* mBackupMethodDef;
|
BfMethodDef* mBackupMethodDef;
|
||||||
|
int mBackupArgMatchCount;
|
||||||
BfMethodDef* mBestMethodDef;
|
BfMethodDef* mBestMethodDef;
|
||||||
BfTypeInstance* mBestMethodTypeInstance;
|
BfTypeInstance* mBestMethodTypeInstance;
|
||||||
BfModuleMethodInstance mBestMethodInstance;
|
BfModuleMethodInstance mBestMethodInstance;
|
||||||
|
@ -152,7 +153,7 @@ public:
|
||||||
Array<BfAmbiguousEntry> mAmbiguousEntries;
|
Array<BfAmbiguousEntry> mAmbiguousEntries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BfTypedValue ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType);
|
BfTypedValue ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType, BfTypeVector* genericArgumentsSubstitute);
|
||||||
bool InferGenericArgument(BfMethodInstance* methodInstance, BfType* argType, BfType* wantType, BfIRValue argValue);
|
bool InferGenericArgument(BfMethodInstance* methodInstance, BfType* argType, BfType* wantType, BfIRValue argValue);
|
||||||
void CompareMethods(BfMethodInstance* prevMethodInstance, BfTypeVector* prevGenericArgumentsSubstitute,
|
void CompareMethods(BfMethodInstance* prevMethodInstance, BfTypeVector* prevGenericArgumentsSubstitute,
|
||||||
BfMethodInstance* newMethodInstance, BfTypeVector* genericArgumentsSubstitute,
|
BfMethodInstance* newMethodInstance, BfTypeVector* genericArgumentsSubstitute,
|
||||||
|
|
|
@ -64,7 +64,8 @@ enum BfEvalExprFlags
|
||||||
BfEvalExprFlags_AllowRefExpr = 0x800,
|
BfEvalExprFlags_AllowRefExpr = 0x800,
|
||||||
BfEvalExprFlags_AllowOutExpr = 0x1000,
|
BfEvalExprFlags_AllowOutExpr = 0x1000,
|
||||||
BfEvalExprFlags_FieldInitializer = 0x2000,
|
BfEvalExprFlags_FieldInitializer = 0x2000,
|
||||||
BfEvalExprFlags_VariableDeclaration = 0x4000
|
BfEvalExprFlags_VariableDeclaration = 0x4000,
|
||||||
|
BfEvalExprFlags_NoAutoComplete = 0x8000
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BfCastFlags
|
enum BfCastFlags
|
||||||
|
@ -1339,8 +1340,7 @@ public:
|
||||||
bool mIsModuleMutable; // Set to false after writing module to disk, can be set back to true after doing extension module
|
bool mIsModuleMutable; // Set to false after writing module to disk, can be set back to true after doing extension module
|
||||||
bool mWroteToLib;
|
bool mWroteToLib;
|
||||||
bool mHadBuildError;
|
bool mHadBuildError;
|
||||||
bool mHadBuildWarning;
|
bool mHadBuildWarning;
|
||||||
bool mHadVarUsage;
|
|
||||||
bool mIgnoreErrors;
|
bool mIgnoreErrors;
|
||||||
bool mIgnoreWarnings;
|
bool mIgnoreWarnings;
|
||||||
bool mSetIllegalSrcPosition;
|
bool mSetIllegalSrcPosition;
|
||||||
|
@ -1362,8 +1362,7 @@ public:
|
||||||
bool CheckProtection(BfProtection protection, bool allowProtected, bool allowPrivate);
|
bool CheckProtection(BfProtection protection, bool allowProtected, bool allowPrivate);
|
||||||
void GetAccessAllowed(BfTypeInstance* checkType, bool& allowProtected, bool& allowPrivate);
|
void GetAccessAllowed(BfTypeInstance* checkType, bool& allowProtected, bool& allowPrivate);
|
||||||
bool CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* memberOwner, BfProtection memberProtection, BfTypeInstance* lookupStartType);
|
bool CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* memberOwner, BfProtection memberProtection, BfTypeInstance* lookupStartType);
|
||||||
void SetElementType(BfAstNode* astNode, BfSourceElementType elementType);
|
void SetElementType(BfAstNode* astNode, BfSourceElementType elementType);
|
||||||
void SetHadVarUsage();
|
|
||||||
BfError* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false);
|
BfError* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false);
|
||||||
BfError* FailAfter(const StringImpl& error, BfAstNode* refNode);
|
BfError* FailAfter(const StringImpl& error, BfAstNode* refNode);
|
||||||
BfError* Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode = NULL, bool isPersistent = false);
|
BfError* Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode = NULL, bool isPersistent = false);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue