diff --git a/IDEHelper/Compiler/BfAutoComplete.cpp b/IDEHelper/Compiler/BfAutoComplete.cpp index 132ce539..44c3ac24 100644 --- a/IDEHelper/Compiler/BfAutoComplete.cpp +++ b/IDEHelper/Compiler/BfAutoComplete.cpp @@ -3301,6 +3301,82 @@ void BfAutoComplete::FixitCheckNamespace(BfTypeDef* activeTypeDef, BfAstNode* ty } } +void BfAutoComplete::FixitAddConstructor(BfTypeInstance *typeInstance) +{ + auto baseType = typeInstance->mBaseType; + auto parser = typeInstance->mTypeDef->mSource->ToParser(); + if (parser != NULL) + { + for (auto methodDef : baseType->mTypeDef->mMethods) + { + if (methodDef->mMethodType != BfMethodType_Ctor) + continue; + if (methodDef->mIsStatic) + continue; + if (methodDef->mProtection <= BfProtection_Private) + continue; + + auto methodInstance = mModule->GetRawMethodInstanceAtIdx(baseType, methodDef->mIdx); + + String ctorShowName; + + int insertPos = FixitGetMemberInsertPos(mModule->mCurTypeInstance->mTypeDef); + String methodStr = "\f\a"; + methodStr += "public this("; + for (int paramIdx = 0; paramIdx < methodInstance->GetParamCount(); paramIdx++) + { + if (paramIdx > 0) + methodStr += ", "; + + switch (methodInstance->GetParamKind(paramIdx)) + { + case BfParamKind_Params: + methodStr += "params "; + } + methodStr += mModule->TypeToString(methodInstance->GetParamType(paramIdx), BfTypeNameFlag_ReduceName); + methodStr += " "; + methodStr += methodInstance->GetParamName(paramIdx); + } + methodStr += ") : base("; + + ctorShowName += "this("; + for (int paramIdx = 0; paramIdx < methodInstance->GetParamCount(); paramIdx++) + { + if (paramIdx > 0) + { + ctorShowName += ", "; + methodStr += ", "; + } + + switch (methodInstance->GetParamKind(paramIdx)) + { + case BfParamKind_Params: + methodStr += "params "; + } + + auto paramType = methodInstance->GetParamType(paramIdx); + if (paramType->IsRef()) + { + switch (((BfRefType*)paramType)->mRefKind) + { + case BfRefType::RefKind_Ref: methodStr += "ref "; break; + case BfRefType::RefKind_Out: methodStr += "out "; break; + case BfRefType::RefKind_Mut: methodStr += "mut "; break; + } + } + + methodStr += methodInstance->GetParamName(paramIdx); + ctorShowName += methodInstance->GetParamName(paramIdx); + } + ctorShowName += ")"; + + methodStr += ")\t"; + AddEntry(AutoCompleteEntry("fixit", StrFormat("Create constructor '%s'\taddMethod|%s|%s", ctorShowName.c_str(), + FixitGetLocation(parser->mParserData, insertPos).c_str(), methodStr.c_str()).c_str())); + } + } +} + void BfAutoComplete::SetResultStringType(BfType * type) { mResultString = ":"; diff --git a/IDEHelper/Compiler/BfAutoComplete.h b/IDEHelper/Compiler/BfAutoComplete.h index 5ebebc92..6c228343 100644 --- a/IDEHelper/Compiler/BfAutoComplete.h +++ b/IDEHelper/Compiler/BfAutoComplete.h @@ -258,6 +258,7 @@ public: void FixitAddMethod(BfTypeInstance* typeInst, const StringImpl& methodName, BfType* returnType, const BfTypeVector& paramTypes, bool wantStatic); void FixitAddNamespace(BfAstNode* refNode, const StringImpl& namespacStr); void FixitCheckNamespace(BfTypeDef* activeTypeDef, BfAstNode* typeRef, BfTokenNode* nextDotToken); + void FixitAddConstructor(BfTypeInstance* typeInstance); void SetResultStringType(BfType* type); }; diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 60029e01..d1d57447 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -5888,6 +5888,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu { error = mModule->Fail(StrFormat("No parameterless constructor is available for base class. Consider calling base constructor '%s'.", mModule->MethodToString(methodInstance).c_str()), refNode); + + auto srcNode = mModule->mCurMethodInstance->mMethodDef->GetRefNode(); + if ((autoComplete != NULL) && (autoComplete->CheckFixit(srcNode))) + autoComplete->FixitAddConstructor(mModule->mCurTypeInstance); } }