});
}
+HRESULT EvalHelpers::EvalGenericFunction(
+ ICorDebugThread *pThread,
+ ICorDebugFunction *pFunc,
+ ICorDebugType **ppTypes,
+ ULONG32 typeCount,
+ ICorDebugValue **ppValues,
+ ULONG32 valueCount,
+ ICorDebugValue **ppResult,
+ int flags)
+{
+ assert((!ppTypes && typeCount == 0) || (ppTypes && typeCount > 0));
+ assert((!ppValues && valueCount == 0) || (ppValues && valueCount > 0));
+
+ if (flags & EVAL_NOFUNCEVAL)
+ return S_OK;
+
+ return m_sharedEvalWaiter->WaitEvalResult(pThread, ppResult,
+ [&](ICorDebugEval *pEval) -> HRESULT
+ {
+ // Note, this code execution protected by EvalWaiter mutex.
+ HRESULT Status;
+ ToRelease<ICorDebugEval2> pEval2;
+ IfFailRet(pEval->QueryInterface(IID_ICorDebugEval2, (LPVOID*) &pEval2));
+ IfFailRet(pEval2->CallParameterizedFunction(
+ pFunc,
+ typeCount,
+ ppTypes,
+ valueCount,
+ ppValues));
+ return S_OK;
+ });
+}
+
static HRESULT GetMethodToken(IMetaDataImport *pMD, mdTypeDef cl, const WCHAR *methodName)
{
ULONG numMethods = 0;
ICorDebugValue **ppEvalResult,
int evalFlags);
+ HRESULT EvalGenericFunction(
+ ICorDebugThread *pThread,
+ ICorDebugFunction *pFunc,
+ ICorDebugType **ppArgsType,
+ ULONG32 ArgsTypeCount,
+ ICorDebugValue **ppArgsValue,
+ ULONG32 ArgsValueCount,
+ ICorDebugValue **ppEvalResult,
+ int evalFlags);
+
HRESULT GetLiteralValue(
ICorDebugThread *pThread,
ICorDebugType *pType,
#include "debugger/evalhelpers.h"
#include "debugger/evalwaiter.h"
#include "debugger/valueprint.h"
+#include "debugger/evalutils.h"
#include "managed/interop.h"
#include "metadata/typeprinter.h"
#include "utils/utf.h"
HRESULT GenericName(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
- // TODO uint32_t Flags = ((FormatFIS*)pArguments)->Flags;
- // TODO int32_t Int = ((FormatFIS*)pArguments)->Int;
- // TODO std::string String = to_utf8(((FormatFIS*)pArguments)->wString);
- return E_NOTIMPL;
+ HRESULT Status;
+ int32_t Int = ((FormatFIS*)pArguments)->Int;
+ std::string String = to_utf8(((FormatFIS*)pArguments)->wString);
+ std::vector<ToRelease<ICorDebugType>> genericValues;
+ std::string generics = ">";
+ genericValues.reserve(Int);
+ for(int i = 0; i < Int; i++)
+ {
+ ToRelease<ICorDebugValue> icdv;
+ ToRelease<ICorDebugType> icdt;
+ ToRelease<ICorDebugValue2> icdv2;
+ std::string genericType;
+ Status = GetFrontStackEntryValue(&icdv, nullptr, evalStack, ed, output);
+ if(Status == S_OK) {
+ IfFailRet(icdv->QueryInterface(IID_ICorDebugValue2, (LPVOID *) &icdv2));
+ IfFailRet(icdv2->GetExactType(&icdt));
+ }
+ else {
+ IfFailRet(GetFrontStackEntryType(&icdt, evalStack, ed, output));
+ }
+ TypePrinter::GetTypeOfValue(icdt, genericType);
+ generics = "," + genericType + generics;
+ genericValues.emplace_back(icdt.Detach());
+ evalStack.pop_front();
+ }
+ generics.erase(0,1);
+ String += "<" + generics;
+ evalStack.emplace_front();
+ evalStack.front().identifiers.emplace_back(std::move(String));
+ evalStack.front().genericTypeCache = std::move(genericValues);
+ evalStack.front().editable = true;
+ return S_OK;
}
HRESULT InvocationExpression(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
{
+ // todo: static const char* extensionAttributeName = "System.Runtime.CompilerServices.ExtensionAttribute..ctor";
int32_t Int = ((FormatFI*)pArguments)->Int;
+
if (Int < 0)
return E_INVALIDARG;
evalStack.pop_front();
}
+ if (evalStack.front().preventBinding)
+ return S_OK;
+
assert(evalStack.front().identifiers.size() > 0); // We must have at least method name (identifier).
// TODO local defined function (compiler will create such function with name like `<Calc1>g__Calc2|0_0`)
- std::string funcName = evalStack.front().identifiers.back();
+ std::string funcNameGenerics = evalStack.front().identifiers.back();
evalStack.front().identifiers.pop_back();
+ std::string funcName;
+ std::vector<std::string> methodGenericStrings = EvalUtils::ParseGenericParams(funcNameGenerics, funcName);
+ size_t pos = funcName.find('`');
+ if (pos != std::string::npos)
+ funcName.resize(pos);
+
if (!evalStack.front().iCorValue && evalStack.front().identifiers.empty())
{
std::string methodClass;
IfFailRet(TypePrinter::GetTypeOfValue(iCorValueArg, funcArgs[i].typeName));
}
+ std::vector<Evaluator::ArgElementType> methodGenerics;
+ methodGenerics.reserve(methodGenericStrings.size());
+ for(ULONG32 i = 0; i < methodGenericStrings.size(); i++)
+ {
+ methodGenerics.emplace_back(ed.pEvaluator->GetElementTypeByTypeName(methodGenericStrings[i]));
+ }
+
ToRelease<ICorDebugFunction> iCorFunc;
- ed.pEvaluator->WalkMethods(iCorType, [&](
+ ed.pEvaluator->WalkMethods(iCorType, methodGenerics, [&](
bool is_static,
const std::string &methodName,
Evaluator::ReturnElementType&,
for (size_t i = 0; i < funcArgs.size(); ++i)
{
- if (funcArgs[i].corType != methodArgs[i].corType ||
- funcArgs[i].typeName != methodArgs[i].typeName)
+ if (funcArgs[i] != methodArgs[i])
return S_OK;
}
return E_ABORT; // Fast exit from cycle.
});
+
if (!iCorFunc)
return E_FAIL;
- evalStack.front().ResetEntry();
-
+ size_t typeArgsCount = evalStack.front().genericTypeCache.size();
ULONG32 realArgsCount = Int + (isInstance ? 1 : 0);
+ std::vector<ICorDebugType*> iCorTypeArgs;
std::vector<ICorDebugValue*> iCorValueArgs;
iCorValueArgs.reserve(realArgsCount);
+ iCorTypeArgs.reserve(typeArgsCount);
+
+ // Place instance value ("this") if not static
if (isInstance)
{
iCorValueArgs.emplace_back(iCorValue.GetPtr());
}
+
+ // Add arguments values
for (int32_t i = 0; i < Int; i++)
{
iCorValueArgs.emplace_back(iCorArgs[i].GetPtr());
}
- Status = ed.pEvalHelpers->EvalFunction(ed.pThread, iCorFunc, nullptr, 0, iCorValueArgs.data(), realArgsCount, &evalStack.front().iCorValue, ed.evalFlags);
+ // Collect type(class)'s generic types if any
+ ToRelease<ICorDebugTypeEnum> pTypeEnum;
+ if (SUCCEEDED(iCorType->EnumerateTypeParameters(&pTypeEnum)))
+ {
+ ICorDebugType *curType;
+ ULONG fetched = 0;
+ while (SUCCEEDED(pTypeEnum->Next(1, &curType, &fetched)) && fetched == 1)
+ {
+ iCorTypeArgs.emplace_back(curType);
+ }
+ }
+
+ // Add method's generic types if any
+ for (size_t i = typeArgsCount; i > 0; i--)
+ {
+ iCorTypeArgs.emplace_back(evalStack.front().genericTypeCache[i-1].GetPtr());
+ }
+
+ evalStack.front().ResetEntry();
+ Status = ed.pEvalHelpers->EvalGenericFunction(ed.pThread, iCorFunc, iCorTypeArgs.data(), (ULONG32)iCorTypeArgs.size(), iCorValueArgs.data(), (ULONG32)iCorValueArgs.size(), &evalStack.front().iCorValue, ed.evalFlags);
// CORDBG_S_FUNC_EVAL_HAS_NO_RESULT: Some Func evals will lack a return value, such as those whose return type is void.
if (Status == CORDBG_S_FUNC_EVAL_HAS_NO_RESULT)
ELEMENT_TYPE_MAX, // Object
ELEMENT_TYPE_I1, // SByte
ELEMENT_TYPE_I2, // Short
- ELEMENT_TYPE_MAX, // String
+ ELEMENT_TYPE_STRING, // String
ELEMENT_TYPE_U2, // UShort
ELEMENT_TYPE_U4, // UInt
ELEMENT_TYPE_U8 // ULong
// TODO uint32_t Flags = ((FormatFI*)pArguments)->Flags;
int32_t Int = ((FormatFI*)pArguments)->Int;
+ std::string String;
evalStack.emplace_front();
if (BasicTypesAlias[Int] == ELEMENT_TYPE_VALUETYPE)
- return CreateValueType(ed.pEvalWaiter, ed.pThread, ed.iCorDecimalClass, &evalStack.front().iCorValuePredefined, nullptr);
+ return CreateValueType(ed.pEvalWaiter, ed.pThread, ed.iCorDecimalClass, &evalStack.front().iCorValue, nullptr);
+ else if (BasicTypesAlias[Int] == ELEMENT_TYPE_STRING)
+ return ed.pEvalHelpers->CreateString(ed.pThread, String, &evalStack.front().iCorValue);
else
- return CreatePrimitiveValue(ed.pThread, &evalStack.front().iCorValuePredefined, BasicTypesAlias[Int], nullptr);
+ return CreatePrimitiveValue(ed.pThread, &evalStack.front().iCorValue, BasicTypesAlias[Int], nullptr);
}
HRESULT AliasQualifiedName(std::list<EvalStackEntry> &evalStack, PVOID pArguments, std::string &output, EvalData &ed)
assert(evalStack.front().identifiers.size() == 1); // Only one unresolved identifier must be here.
std::string identifier = std::move(evalStack.front().identifiers[0]);
+ std::vector<ToRelease<ICorDebugType>> iCorDebugTypes;
+ size_t genericsCount = evalStack.front().genericTypeCache.size();
+ if (genericsCount > 0)
+ {
+ iCorDebugTypes = std::move(evalStack.front().genericTypeCache);
+ }
evalStack.pop_front();
-
if (!evalStack.front().preventBinding)
+ {
evalStack.front().identifiers.emplace_back(std::move(identifier));
-
+ evalStack.front().genericTypeCache.clear(); // We need method's generics only, so remove all previous if exist.
+ if (genericsCount > 0)
+ {
+ evalStack.front().genericTypeCache = std::move(iCorDebugTypes);
+ }
+ }
return S_OK;
}
uint32_t size = 0;
PVOID szPtr = &size;
- if (evalStack.front().iCorValuePredefined)
+ if (evalStack.front().iCorValue)
{
// predefined type
CorElementType elType;
- IfFailRet(evalStack.front().iCorValuePredefined->GetType(&elType));
+ IfFailRet(evalStack.front().iCorValue->GetType(&elType));
if(elType == ELEMENT_TYPE_CLASS)
{
ToRelease<ICorDebugValue> iCorValue;
- IfFailRet(DereferenceAndUnboxValue(evalStack.front().iCorValuePredefined, &iCorValue, nullptr));
+ IfFailRet(DereferenceAndUnboxValue(evalStack.front().iCorValue, &iCorValue, nullptr));
IfFailRet(iCorValue->GetSize(&size));
}
else
{
- IfFailRet(evalStack.front().iCorValuePredefined->GetSize(&size));
+ IfFailRet(evalStack.front().iCorValue->GetSize(&size));
}
}
else
std::vector<std::string> identifiers;\r
// Resolved to value identifiers.\r
ToRelease<ICorDebugValue> iCorValue;\r
- // Predefined types values\r
- ToRelease<ICorDebugValue> iCorValuePredefined;\r
+ // Generic types cache. Note, finally we need the method's generic types only, i.e. the last element of\r
+ // identifiers vector. The other type(class)'s generics can easily be got from the corresponding iCorDebugType\r
+ std::vector<ToRelease<ICorDebugType>> genericTypeCache;\r
// Prevent future binding in case of conditional access with nulled object (`a?.b`, `a?[1]`, ...).\r
// Note, this state could be related to iCorValue only (iCorValue must be checked for null first).\r
bool preventBinding;\r
{\r
identifiers.clear();\r
iCorValue.Free();\r
- iCorValuePredefined.Free();\r
+ genericTypeCache.clear();\r
preventBinding = false;\r
if (resetLiteral == ResetLiteralStatus::Yes)\r
literal = false;\r
#include "utils/utf.h"
#include "metadata/modules.h"
#include "metadata/typeprinter.h"
+#include "metadata/attributes.h"
#include "valueprint.h"
#include "managed/interop.h"
namespace netcoredbg
{
+bool Evaluator::ArgElementType::isAlias(const CorElementType type1, const CorElementType type2, const std::string& name2)
+{
+ static const std::unordered_map<CorElementType, ArgElementType> aliases = {
+ {ELEMENT_TYPE_BOOLEAN, {ELEMENT_TYPE_VALUETYPE, "System.Boolean"}},
+ {ELEMENT_TYPE_CHAR, {ELEMENT_TYPE_VALUETYPE, "System.Char"}},
+ {ELEMENT_TYPE_I1, {ELEMENT_TYPE_VALUETYPE, "System.Byte"}},
+ {ELEMENT_TYPE_U1, {ELEMENT_TYPE_VALUETYPE, "System.SByte"}},
+ {ELEMENT_TYPE_R8, {ELEMENT_TYPE_VALUETYPE, "System.Double"}},
+ {ELEMENT_TYPE_R4, {ELEMENT_TYPE_VALUETYPE, "System.Single"}},
+ {ELEMENT_TYPE_I4, {ELEMENT_TYPE_VALUETYPE, "System.Int32"}},
+ {ELEMENT_TYPE_U4, {ELEMENT_TYPE_VALUETYPE, "System.UInt32"}},
+ {ELEMENT_TYPE_I8, {ELEMENT_TYPE_VALUETYPE, "System.Int64"}},
+ {ELEMENT_TYPE_U8, {ELEMENT_TYPE_VALUETYPE, "System.UInt64"}},
+ {ELEMENT_TYPE_OBJECT, {ELEMENT_TYPE_CLASS, "System.Object"}},
+ {ELEMENT_TYPE_I2, {ELEMENT_TYPE_VALUETYPE, "System.Int16"}},
+ {ELEMENT_TYPE_U2, {ELEMENT_TYPE_VALUETYPE, "System.UInt16"}},
+ {ELEMENT_TYPE_STRING, {ELEMENT_TYPE_CLASS, "System.String"}}
+ };
+
+ auto found = aliases.find(type1);
+ if (found != aliases.end())
+ {
+ if (found->second.corType == type2 && found->second.typeName == name2)
+ return true;
+ }
+ return false;
+}
+
+bool Evaluator::ArgElementType::areEqual(const ArgElementType& arg)
+{
+ if (corType == arg.corType && typeName == arg.typeName)
+ return true;
+ if (isAlias(corType, arg.corType, arg.typeName))
+ return true;
+ if (isAlias(arg.corType, corType, typeName))
+ return true;
+ return false;
+}
+
+Evaluator::ArgElementType Evaluator::GetElementTypeByTypeName(const std::string typeName)
+{
+ static const std::unordered_map<std::string, Evaluator::ArgElementType> stypes = {
+ {"void", {ELEMENT_TYPE_VALUETYPE, "System.Void"}},
+ {"bool", {ELEMENT_TYPE_VALUETYPE, "System.Boolean"}},
+ {"byte", {ELEMENT_TYPE_VALUETYPE, "System.Byte"}},
+ {"sbyte", {ELEMENT_TYPE_VALUETYPE, "System.SByte"}},
+ {"char", {ELEMENT_TYPE_VALUETYPE, "System.Char"}},
+ {"decimal", {ELEMENT_TYPE_VALUETYPE, "System.Decimal"}},
+ {"double", {ELEMENT_TYPE_VALUETYPE, "System.Double"}},
+ {"float", {ELEMENT_TYPE_VALUETYPE, "System.Single"}},
+ {"int", {ELEMENT_TYPE_VALUETYPE, "System.Int32"}},
+ {"uint", {ELEMENT_TYPE_VALUETYPE, "System.UInt32"}},
+ {"long", {ELEMENT_TYPE_VALUETYPE, "System.Int64"}},
+ {"ulong", {ELEMENT_TYPE_VALUETYPE, "System.UInt64"}},
+ {"object", {ELEMENT_TYPE_CLASS, "System.Object"}},
+ {"short", {ELEMENT_TYPE_VALUETYPE, "System.Int16"}},
+ {"ushort", {ELEMENT_TYPE_VALUETYPE, "System.UInt16"}},
+ {"string", {ELEMENT_TYPE_CLASS, "System.String"}},
+ {"IntPtr", {ELEMENT_TYPE_VALUETYPE, "System.IntPtr"}},
+ {"UIntPtr", {ELEMENT_TYPE_VALUETYPE, "System.UIntPtr"}}
+ };
+
+ Evaluator::ArgElementType userType;
+ auto found = stypes.find(typeName);
+ if (found != stypes.end())
+ {
+ return found->second;
+ }
+ userType.corType = ELEMENT_TYPE_CLASS;
+ userType.typeName = typeName;
+ return userType;
+}
+
HRESULT Evaluator::GetElement(ICorDebugValue *pInputValue, std::vector<ULONG32> &indexes, ICorDebugValue **ppResultValue)
{
HRESULT Status;
static HRESULT ParseElementType(IMetaDataImport *pMD,
PCCOR_SIGNATURE *ppSig,
Evaluator::ArgElementType &argElementType,
- std::vector<Evaluator::ArgElementType> &genericArgs,
+ std::vector<Evaluator::ArgElementType> &typeGenerics,
+ std::vector<Evaluator::ArgElementType> &methodGenerics,
bool addCorTypeName = false)
{
HRESULT Status;
break;
case ELEMENT_TYPE_SZARRAY:
- if (FAILED(Status = ParseElementType(pMD, ppSig, argElementType, genericArgs, true)) || Status == S_FALSE)
+ if (FAILED(Status = ParseElementType(pMD, ppSig, argElementType, typeGenerics, methodGenerics, true)) || Status == S_FALSE)
return Status;
argElementType.corType = (CorElementType)corType;
argElementType.typeName += "[]";
break;
case ELEMENT_TYPE_ARRAY:
{
- if (FAILED(Status = ParseElementType(pMD, ppSig, argElementType, genericArgs, true)) || Status == S_FALSE)
+ if (FAILED(Status = ParseElementType(pMD, ppSig, argElementType, typeGenerics, methodGenerics, true)) || Status == S_FALSE)
return Status;
argElementType.corType = (CorElementType)corType;
// Parse for the rank
case ELEMENT_TYPE_VAR: // Generic parameter in a generic type definition, represented as number
*ppSig += CorSigUncompressData(*ppSig, &argNum);
- if (argNum >= genericArgs.size())
+ if (argNum >= typeGenerics.size())
return S_FALSE;
else
{
- argElementType = genericArgs[argNum];
+ argElementType = typeGenerics[argNum];
if (addCorTypeName && argElementType.typeName.empty())
GetCorTypeName(argElementType.corType, argElementType.typeName);
}
break;
+
+ case ELEMENT_TYPE_MVAR: // Generic parameter in a generic method definition, represented as number
+ *ppSig += CorSigUncompressData(*ppSig, &argNum);
+ if (argNum >= methodGenerics.size())
+ return S_FALSE;
+ else
+ {
+ argElementType = methodGenerics[argNum];
+ if (addCorTypeName && argElementType.typeName.empty())
+ GetCorTypeName(argElementType.corType, argElementType.typeName);
+ }
+ break;
+
+ case ELEMENT_TYPE_GENERICINST: // A type modifier for generic types - List<>, Dictionary<>, ...
+ ULONG number;
+ mdToken token;
+ *ppSig += CorSigUncompressData(*ppSig, &corType);
+ if(corType != ELEMENT_TYPE_CLASS && corType != ELEMENT_TYPE_VALUETYPE)
+ return S_FALSE;
+ *ppSig += CorSigUncompressToken(*ppSig, &token);
+ argElementType.corType = (CorElementType)corType;
+ IfFailRet(TypePrinter::NameForTypeByToken(token, pMD, argElementType.typeName, nullptr));
+ *ppSig += CorSigUncompressData(*ppSig, &number);
+ for(ULONG i = 0; i < number; i++)
+ {
+ Evaluator::ArgElementType mycop; // Not needed at the moment
+ if (FAILED(Status = ParseElementType(pMD, ppSig, mycop, typeGenerics, methodGenerics, true)) || Status == S_FALSE)
+ return Status;
+ }
+ break;
+
// TODO
case ELEMENT_TYPE_U: // "nuint" - error CS8652: The feature 'native-sized integers' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
case ELEMENT_TYPE_I: // "nint" - error CS8652: The feature 'native-sized integers' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
case ELEMENT_TYPE_TYPEDBYREF:
case ELEMENT_TYPE_PTR: // int* ptr (unsafe code only)
case ELEMENT_TYPE_BYREF: // ref, in, out
- case ELEMENT_TYPE_MVAR: // Generic parameter in a generic method definition, represented as number
- case ELEMENT_TYPE_GENERICINST: // A type modifier for generic types - List<>, Dictionary<>, ...
case ELEMENT_TYPE_CMOD_REQD:
case ELEMENT_TYPE_CMOD_OPT:
return S_FALSE;
IfFailRet(pInputTypeValue->QueryInterface(IID_ICorDebugValue2, (LPVOID *) &iCorValue2));
ToRelease<ICorDebugType> iCorType;
IfFailRet(iCorValue2->GetExactType(&iCorType));
+ std::vector<Evaluator::ArgElementType> methodGenerics;
- return WalkMethods(iCorType, cb);
+ return WalkMethods(iCorType, methodGenerics, cb);
}
-static HRESULT InternalWalkMethods(ICorDebugType *pInputType, Evaluator::WalkMethodsCallback cb)
+static HRESULT InternalWalkMethods(ICorDebugType *pInputType, std::vector<Evaluator::ArgElementType> &methodGenerics, Evaluator::WalkMethodsCallback cb)
{
HRESULT Status;
ToRelease<ICorDebugClass> pClass;
ToRelease<IMetaDataImport> pMD;
IfFailRet(pMDUnknown->QueryInterface(IID_IMetaDataImport, (LPVOID*) &pMD));
- std::vector<Evaluator::ArgElementType> genericArgs;
+ std::vector<Evaluator::ArgElementType> typeGenerics;
ToRelease<ICorDebugTypeEnum> paramTypes;
if (SUCCEEDED(pInputType->EnumerateTypeParameters(¶mTypes)))
pCurrentTypeParam->GetType(&argElType.corType);
if(argElType.corType == ELEMENT_TYPE_VALUETYPE || argElType.corType == ELEMENT_TYPE_CLASS)
IfFailRet(TypePrinter::NameForTypeByType(pCurrentTypeParam, argElType.typeName));
- genericArgs.emplace_back(argElType);
+ typeGenerics.emplace_back(argElType);
pCurrentTypeParam.Free();
}
}
szFunctionName, _countof(szFunctionName), &nameLen,
&methodAttr, &pSig, &cbSig, nullptr, nullptr)))
continue;
+ ULONG gParams; // Count of signature generics
ULONG cParams; // Count of signature parameters.
ULONG elementSize;
ULONG convFlags;
elementSize = CorSigUncompressData(pSig, &convFlags);
pSig += elementSize;
- // TODO add VARARG and GENERIC methods support.
- if ((convFlags & SIG_METHOD_VARARG) ||
- (convFlags & SIG_METHOD_GENERIC))
+ // TODO add VARARG methods support.
+ if (convFlags & SIG_METHOD_VARARG)
continue;
- // 2. count of params
+ // 2. count of generics if any
+ if (convFlags & SIG_METHOD_GENERIC)
+ {
+ elementSize = CorSigUncompressData(pSig, &gParams);
+ pSig += elementSize;
+ }
+
+ // 3. count of params
elementSize = CorSigUncompressData(pSig, &cParams);
pSig += elementSize;
- // 3. return type
+ // 4. return type
Evaluator::ArgElementType returnElementType;
- IfFailRet(ParseElementType(pMD, &pSig, returnElementType, genericArgs));
+ IfFailRet(ParseElementType(pMD, &pSig, returnElementType, typeGenerics, methodGenerics));
if (Status == S_FALSE)
continue;
- // 4. get next element from method signature
+ // 5. get next element from method signature
std::vector<Evaluator::ArgElementType> argElementTypes(cParams);
for (ULONG i = 0; i < cParams; ++i)
{
- IfFailRet(ParseElementType(pMD, &pSig, argElementTypes[i], genericArgs));
+ IfFailRet(ParseElementType(pMD, &pSig, argElementTypes[i], typeGenerics, methodGenerics));
if (Status == S_FALSE)
break;
}
ToRelease<ICorDebugType> iCorBaseType;
if(SUCCEEDED(pInputType->GetBase(&iCorBaseType)) && iCorBaseType != NULL)
{
- IfFailRet(InternalWalkMethods(iCorBaseType, cb));
+ IfFailRet(InternalWalkMethods(iCorBaseType, methodGenerics, cb));
}
return S_OK;
}
-HRESULT Evaluator::WalkMethods(ICorDebugType *pInputType, Evaluator::WalkMethodsCallback cb)
+HRESULT Evaluator::WalkMethods(ICorDebugType *pInputType, std::vector<Evaluator::ArgElementType> &methodGenerics, Evaluator::WalkMethodsCallback cb)
{
- return InternalWalkMethods(pInputType, cb);
+ return InternalWalkMethods(pInputType, methodGenerics, cb);
}
static HRESULT InternalSetValue(EvalStackMachine *pEvalStackMachine, EvalHelpers *pEvalHelpers, ICorDebugThread *pThread, FrameLevel frameLevel,
}
} // namespace netcoredbg
+
ArgElementType() :
corType(ELEMENT_TYPE_END)
{}
+
+ ArgElementType(CorElementType t, std::string n)
+ {
+ corType = t;
+ typeName = n;
+ }
+
+ bool isAlias (const CorElementType type1, const CorElementType type2, const std::string& name2);
+ bool areEqual(const ArgElementType& arg);
+ inline bool operator==(const ArgElementType& arg) { return areEqual(arg); }
+ inline bool operator!=(const ArgElementType& arg) { return !areEqual(arg); }
};
+
typedef ArgElementType ReturnElementType;
struct SetterData
bool &thisParam);
HRESULT GetElement(ICorDebugValue *pInputValue, std::vector<ULONG32> &indexes, ICorDebugValue **ppResultValue);
- HRESULT WalkMethods(ICorDebugType *pInputType, WalkMethodsCallback cb);
+ HRESULT WalkMethods(ICorDebugType *pInputType, std::vector<Evaluator::ArgElementType> &methodGenerics, WalkMethodsCallback cb);
HRESULT WalkMethods(ICorDebugValue *pInputTypeValue, WalkMethodsCallback cb);
-
HRESULT SetValue(ICorDebugThread *pThread, FrameLevel frameLevel, ICorDebugValue *pValue, SetterData *setterData,
const std::string &value, int evalFlags, std::string &output);
+ ArgElementType GetElementTypeByTypeName(const std::string typeName);
+
private:
std::shared_ptr<Modules> m_sharedModules;
namespace EvalUtils
{
- static std::vector<std::string> ParseGenericParams(const std::string &identifier, std::string &typeName)
+ std::vector<std::string> ParseGenericParams(const std::string &identifier, std::string &typeName)
{
std::vector<std::string> result;
std::vector<std::string> ParseType(const std::string &expression, std::vector<int> &ranks);
HRESULT FindType(const std::vector<std::string> &identifiers, int &nextIdentifier, ICorDebugThread *pThread, Modules *pModules,
ICorDebugModule *pModule, ICorDebugType **ppType, ICorDebugModule **ppModule = nullptr);
+ std::vector<std::string> ParseGenericParams(const std::string &identifier, std::string &typeName);
}
} // namespace netcoredbg
std::list<ToRelease<ICorDebugFunction>> listClearCache;
std::list<ToRelease<ICorDebugFunction>> listUpdateApplication;
+ std::vector<Evaluator::ArgElementType> emptyVector;
for (auto &updateHandlerType : modulesUpdateHandlerTypes)
{
- pEvaluator->WalkMethods(updateHandlerType.GetPtr(), [&](
+ pEvaluator->WalkMethods(updateHandlerType.GetPtr(), emptyVector, [&](
bool is_static,
const std::string &methodName,
Evaluator::ReturnElementType &methodRet,
case SyntaxKind.StringLiteralExpression:
stackMachineProgram.Commands.Add(new OneOperandCommand(node.Kind(), CurrentScopeFlags.Peek(), node.GetFirstToken().Value));
break;
-/* TODO
+
case SyntaxKind.GenericName:
// GenericName
// \ TypeArgumentList
}
stackMachineProgram.Commands.Add(new TwoOperandCommand(node.Kind(), CurrentScopeFlags.Peek(), node.GetFirstToken().Value, GenericNameArgs));
break;
-*/
+
case SyntaxKind.InvocationExpression:
/* TODO
case SyntaxKind.ObjectCreationExpression:
case SyntaxKind.ConditionalAccessExpression:
case SyntaxKind.ArgumentList:
case SyntaxKind.ParenthesizedExpression:
-/* TODO
case SyntaxKind.TypeArgumentList:
+/* TODO
case SyntaxKind.OmittedTypeArgument:
case SyntaxKind.UncheckedExpression:
case SyntaxKind.CheckedExpression:
{
sb.AppendFormat(" {0}\n", command.ToString());
}
-
return sb.ToString();
}
#endif
public class MethodCallTest2
{
public static MethodCallTest1 member1 = new MethodCallTest1();
+ public MethodCallTest1 nullMember;
}
public class MethodCallTest3
}
MethodCallTest1 MethodCallTest = new MethodCallTest1();
+ MethodCallTest1 methodCallTest1Null;
+ MethodCallTest2 methodCallTest2 = new MethodCallTest2();
+ MethodCallTest2 methodCallTest2Null;
test_child TestCallChild = new test_child();
test_parent TestCallParentOverride = new test_child();
test_parent TestCallParent = new test_parent();
Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "MethodCallTest?.Calc1()", "Error");
Context.GetAndCheckValue(@"__FILE__:__LINE__", "6", "int", "MethodCallTest?.Calc2()");
Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"MITestEvaluate.MethodCallTest1\\\"", "string", "MethodCallTest?.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "null", "MITestEvaluate.MethodCallTest1", "methodCallTest1Null?.Calc2()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "{System.NullReferenceException}", "System.NullReferenceException", "methodCallTest1Null.Calc2()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "null", "MITestEvaluate.MethodCallTest2", "methodCallTest2Null?.member.Calc2()");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "methodCallTest2Null.member.Calc2()", "Error");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "{System.NullReferenceException}", "System.NullReferenceException", "methodCallTest2.nullMember.Calc2()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "null", "MITestEvaluate.MethodCallTest1", "methodCallTest2.nullMember?.Calc2()");
// Call non static method in static member.
Context.GetAndCheckValue(@"__FILE__:__LINE__", "6", "int", "MITestEvaluate.MethodCallTest2.member1.Calc2()");
{\r
class Program\r
{\r
+ public class MY\r
+ {\r
+ public int m;\r
+ public static int retme(int arg1)\r
+ {\r
+ return arg1;\r
+ }\r
+ }\r
+\r
+ public class TestNested<X,Y>\r
+ {\r
+ public class Nested<A,B>\r
+ {\r
+ public static MY my;\r
+\r
+ public A test1(A arga)\r
+ {\r
+ return arga;\r
+ }\r
+\r
+ public B test1(B argb)\r
+ {\r
+ return argb;\r
+ }\r
+\r
+ public C test3<C>(A arga, B argb, C argc)\r
+ {\r
+ return argc;\r
+ }\r
+\r
+ public static A static_test1(A arga)\r
+ {\r
+ return arga;\r
+ }\r
+\r
+ public static B static_test1(B argb)\r
+ {\r
+ return argb;\r
+ }\r
+\r
+ public static C static_test3<C>(A arga, B argb, C argc)\r
+ {\r
+ return argc;\r
+ }\r
+ }\r
+\r
+ public static Nested<X,Y> static_nested;\r
+ public Nested<X,Y> nested;\r
+ public Nested<X,Y> uninitialized;\r
+ public TestNested()\r
+ {\r
+ nested = new Nested<X,Y>();\r
+ }\r
+ }\r
+\r
public class TestGeneric<T,U>\r
{\r
+ public T test1(T argt)\r
+ {\r
+ return argt;\r
+ }\r
\r
- public T test1(T arg1)\r
+ public U test1(U argu)\r
{\r
- return arg1;\r
+ return argu;\r
}\r
\r
- public W test2<W>(W arg2)\r
+ public T test12(T argt, U argu)\r
{\r
- return arg2;\r
+ return argt;\r
}\r
\r
- static public T static_test1(T arg1)\r
+ public U test21(U argu, T argt)\r
{\r
- return arg1;\r
+ return argu;\r
+ }\r
+\r
+ public W test2<W>(W argw)\r
+ {\r
+ return argw;\r
+ }\r
+\r
+ public W test3<W>(T argt, U argu, W argw)\r
+ {\r
+ return argw;\r
}\r
\r
- static public W static_test2<W>(W arg2)\r
+ public W test41<W,Y,Z>(W argw, Y argy, Z argz, T argt)\r
{\r
- return arg2;\r
+ return argw;\r
+ }\r
+\r
+ public Y test42<W,Y,Z>(W argw, Y argy, Z argz, T argt)\r
+ {\r
+ return argy;\r
+ }\r
+\r
+ public Z test43<W,Y,Z>(W argw, Y argy, Z argz, T argt)\r
+ {\r
+ return argz;\r
+ }\r
+\r
+ public T test44<W,Y,Z>(W argw, Y argy, Z argz, T argt)\r
+ {\r
+ return argt;\r
+ }\r
+\r
+ static public T static_test1(T argt)\r
+ {\r
+ return argt;\r
+ }\r
+\r
+ static public U static_test1(U argu)\r
+ {\r
+ return argu;\r
+ }\r
+\r
+ static public W static_test2<W>(W argw)\r
+ {\r
+ return argw;\r
+ }\r
+\r
+ static public W static_test3<W>(T argt, U argu, W argw)\r
+ {\r
+ return argw;\r
+ }\r
+\r
+ static public W static_test41<W,Y,Z>(W argw, Y argy, Z argz, T argt)\r
+ {\r
+ return argw;\r
+ }\r
+\r
+ static public Y static_test42<W,Y,Z>(W argw, Y argy, Z argz, T argt)\r
+ {\r
+ return argy;\r
+ }\r
+\r
+ static public Z static_test43<W,Y,Z>(W argw, Y argy, Z argz, T argt)\r
+ {\r
+ return argz;\r
+ }\r
+\r
+ static public T static_test44<W,Y,Z>(W argw, Y argy, Z argz, T argt)\r
+ {\r
+ return argt;\r
}\r
\r
public T i1;\r
\r
public void test_func()\r
{\r
+ MY my = new MY();\r
Console.WriteLine("test_func()"); Label.Breakpoint("BREAK2");\r
\r
Label.Checkpoint("test_func", "test_set_value", (Object context) => {\r
Context.GetAndCheckValue(@"__FILE__:__LINE__", "456", "int", "static_p_i1");\r
Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"test_string4\\\"", "string", "static_p_s1");\r
\r
- // FIXME\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", "5", "int", "test1(5)");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", "10", "int", "test2<int>(10)");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", "15", "int", "static_test1(15)");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", "20", "int", "static_test2<int>(20)");\r
+ // Instance methods\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "5", "int", "test1(5)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"five\\\"", "string", "test1(\\\"five\\\")");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test1(false)", "Error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "5", "int", "test12(5,\\\"five\\\")");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"five\\\"", "string", "test21(\\\"five\\\",5)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "10", "int", "test2<int>(10)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "test2<bool>(false)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "97 'a'", "char", "test2<char>('a')");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"abc\\\"", "string", "test2<string>(\\\"abc\\\")");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "{MITestGeneric.Program.MY}", "MITestGeneric.Program.MY", "test2<MY>(my)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "97 'a'", "char", "test3<char>(101,\\\"string\\\",'a')");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test3<bool>(101,\\\"string\\\",'a')", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test3<char>(101,'a','a')", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test3<char>('a',\\\"string\\\",'a')", "Error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "97 'a'", "char", "test41<char,bool,string>('a',true,\\\"string\\\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "test42<char,bool,string>('a',true,\\\"string\\\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"string\\\"", "string", "test43<char,bool,string>('a',true,\\\"string\\\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "41", "int", "test44<char,bool,string>('a',true,\\\"string\\\", 41)");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test44<bool,string,char>('a',true,\\\"string\\\", 41)", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test44<string,char,bool>('a',true,\\\"string\\\", 41)", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "test44<bool,char,string>('a',true,\\\"string\\\", 41)", "Error");\r
+\r
+ // Static methods\r
+\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "15", "int", "static_test1(15)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"fifteen\\\"", "string", "static_test1(\\\"fifteen\\\")");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "static_test1(false)", "Error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "20", "int", "static_test2<int>(20)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "static_test2<bool>(true)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "120 'x'", "char", "static_test2<char>('x')");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"xyz\\\"", "string", "static_test2<string>(\\\"xyz\\\")");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "{MITestGeneric.Program.MY}", "MITestGeneric.Program.MY", "static_test2<MY>(my)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "97 'a'", "char", "static_test3<char>(101,\\\"string\\\",'a')");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "static_test3<bool>(101,\\\"string\\\",'a')", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "static_test3<char>(101,'a','a')", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "static_test3<char>('a',\\\"string\\\",'a')", "Error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "97 'a'", "char", "static_test41<char,bool,string>('a',true,\\\"string\\\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "static_test42<char,bool,string>('a',true,\\\"string\\\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"string\\\"", "string", "static_test43<char,bool,string>('a',true,\\\"string\\\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "41", "int", "static_test44<char,bool,string>('a',true,\\\"string\\\", 41)");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "static_test44<bool,string,char>('a',true,\\\"string\\\", 41)", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "static_test44<string,char,bool>('a',true,\\\"string\\\", 41)", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "static_test44<bool,char,string>('a',true,\\\"string\\\", 41)", "Error");\r
\r
// Test set value.\r
\r
TestGeneric<int,string>.static_s1 = "test_string3";\r
TestGeneric<int,string>.static_p_i1 = 456;\r
TestGeneric<int,string>.static_p_s1 = "test_string4";\r
+ MY my = new MY();\r
+ TestNested<char,int> testnested = new TestNested<char,int>();\r
+ TestNested<char,int> uninitialized;\r
\r
ttt.test_func(); Label.Breakpoint("BREAK1");\r
\r
Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "ttt.static_p_i1", "error");\r
Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "ttt.static_p_s1", "error");\r
\r
- // FIXME debugger must be fixed first\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", "345", "int", "TestGeneric<int, string>.static_i1");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"test_string3\\\"", "string", "TestGeneric<int, string>.static_s1");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", "456", "int", "TestGeneric<int, string>.static_p_i1");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"test_string4\\\"", "string", "TestGeneric<int, string>.static_p_s1");\r
-\r
- // FIXME debugger must be fixed first\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", "5", "int", "ttt.test1(5)");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", "10", "int", "ttt.test2<int>(10)");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", "15", "int", "TestGeneric<int,string>.static_test1(15)");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", "20", "int", "TestGeneric<int,string>.static_test2<int>(20)");\r
+ // Static class members\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "345", "int", "TestGeneric<int, string>.static_i1");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"test_string3\\\"", "string", "TestGeneric<int, string>.static_s1");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "456", "int", "TestGeneric<int, string>.static_p_i1");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"test_string4\\\"", "string", "TestGeneric<int, string>.static_p_s1");\r
+\r
+ // Instance methods\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "5", "int", "ttt.test1(5)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"five\\\"", "string", "ttt.test1(\\\"five\\\")");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "ttt.test1(false)", "Error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "5", "int", "ttt.test12(5,\\\"five\\\")");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"five\\\"", "string", "ttt.test21(\\\"five\\\",5)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "10", "int", "ttt.test2<int>(10)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "false", "bool", "ttt.test2<bool>(false)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "97 'a'", "char", "ttt.test2<char>('a')");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"abc\\\"", "string", "ttt.test2<string>(\\\"abc\\\")");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "{MITestGeneric.Program.MY}", "MITestGeneric.Program.MY", "ttt.test2<MY>(my)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "97 'a'", "char", "ttt.test3<char>(101,\\\"string\\\",'a')");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "ttt.test3<bool>(101,\\\"string\\\",'a')", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "ttt.test3<char>(101,'a','a')", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "ttt.test3<char>('a',\\\"string\\\",'a')", "Error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "97 'a'", "char", "ttt.test41<char,bool,string>('a',true,\\\"string\\\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "ttt.test42<char,bool,string>('a',true,\\\"string\\\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"string\\\"", "string", "ttt.test43<char,bool,string>('a',true,\\\"string\\\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "41", "int", "ttt.test44<char,bool,string>('a',true,\\\"string\\\", 41)");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "ttt.test44<bool,string,char>('a',true,\\\"string\\\", 41)", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "ttt.test44<string,char,bool>('a',true,\\\"string\\\", 41)", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "ttt.test44<bool,char,string>('a',true,\\\"string\\\", 41)", "Error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "97 'a'", "char", "testnested.nested.test1('a')");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "123", "int", "testnested.nested.test1(123)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "789", "int", "testnested.nested.test3<int>('c',456,789)");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "testnested.nested.test3<int>(false,456,789)", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "testnested.nested.test3<int>('c',456,\\\"abc\\\")", "Error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"cde\\\"", "string", "testnested.nested.test3<string>('c',456,\\\"cde\\\")");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "testnested.nested.test3<string>(false,456,\\\"cde\\\")", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "testnested.nested.test3<string>('c',456,789)", "Error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "null", "MITestGeneric.Program.TestNested<char, int>", "uninitialized?.uninitialized?.test3<string>('c',456,\\\"cde\\\")");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "null", "MITestGeneric.Program.TestNested<char, int>.Nested<char, int>", "testnested.uninitialized?.test3<string>('c',456,\\\"cde\\\")");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "uninitialized.uninitialized?.test3<string>('c',456,\\\"cde\\\")", "error:");\r
+\r
+ // Static methods\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "15", "int", "TestGeneric<int,string>.static_test1(15)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"fifteen\\\"", "string", "TestGeneric<int,string>.static_test1(\\\"fifteen\\\")");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_test1(false)", "Error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "20", "int", "TestGeneric<int,string>.static_test2<int>(20)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "TestGeneric<int,string>.static_test2<bool>(true)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "120 'x'", "char", "TestGeneric<int,string>.static_test2<char>('x')");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"xyz\\\"", "string", "TestGeneric<int,string>.static_test2<string>(\\\"xyz\\\")");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "{MITestGeneric.Program.MY}", "MITestGeneric.Program.MY", "TestGeneric<int,string>.static_test2<MY>(my)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "97 'a'", "char", "TestGeneric<int,string>.static_test3<char>(101,\\\"string\\\",'a')");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_test3<bool>(101,\\\"string\\\",'a')", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_test3<char>(101,'a','a')", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_test3<char>('a',\\\"string\\\",'a')", "Error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "97 'a'", "char", "TestGeneric<int,string>.static_test41<char,bool,string>('a',true,\\\"string\\\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "TestGeneric<int,string>.static_test42<char,bool,string>('a',true,\\\"string\\\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"string\\\"", "string", "TestGeneric<int,string>.static_test43<char,bool,string>('a',true,\\\"string\\\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "41", "int", "TestGeneric<int,string>.static_test44<char,bool,string>('a',true,\\\"string\\\", 41)");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_test44<bool,string,char>('a',true,\\\"string\\\", 41)", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_test44<string,char,bool>('a',true,\\\"string\\\", 41)", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_test44<bool,char,string>('a',true,\\\"string\\\", 41)", "Error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "97 'a'", "char", "TestNested<int,string>.Nested<char,bool>.static_test1('a')");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "true", "bool", "TestNested<int,string>.Nested<char,bool>.static_test1(true)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", "\\\"abc\\\"", "string", "TestNested<int,string>.Nested<char,bool>.static_test3<string>('a', true, \\\"abc\\\")");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "TestNested<int,string>.Nested<char,bool>.static_test1(\\\"xyz\\\")", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "TestNested<int,string>.Nested<char,bool>.static_test3<string>('a', true, 123)", "Error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "TestNested<int,string>.Nested<char,bool>.static_test3<string>(123, true, \\\"abc\\\")", "Error");\r
\r
Context.Continue(@"__FILE__:__LINE__");\r
});\r
Context.CreateAndCompareVar(@"__FILE__:__LINE__", "ttt.p_s1", "\\\"changed_string2\\\"");\r
\r
// FIXME debugger must be fixed first\r
- //Context.CreateAndAssignVar(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_i1", "777");\r
- //Context.CreateAndAssignVar(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_s1", "\"changed_string3\"", true);\r
- //Context.CreateAndCompareVar(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_s1", "\\\"changed_string3\\\"");\r
+ Context.CreateAndAssignVar(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_i1", "777");\r
+ Context.CreateAndAssignVar(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_s1", "\"changed_string3\"", true);\r
+ Context.CreateAndCompareVar(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_s1", "\\\"changed_string3\\\"");\r
\r
// FIXME debugger must be fixed first\r
- //Context.CreateAndAssignVar(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_p_i1", "888");\r
- //Context.CreateAndAssignVar(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_p_s1", "\"changed_string4\"", true);\r
- //Context.CreateAndCompareVar(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_p_s1", "\\\"changed_string4\\\"");\r
+ Context.CreateAndAssignVar(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_p_i1", "888");\r
+ Context.CreateAndAssignVar(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_p_s1", "\"changed_string4\"", true);\r
+ Context.CreateAndCompareVar(@"__FILE__:__LINE__", "TestGeneric<int,string>.static_p_s1", "\\\"changed_string4\\\"");\r
\r
Context.Continue(@"__FILE__:__LINE__");\r
});\r
public class MethodCallTest2
{
public static MethodCallTest1 member1 = new MethodCallTest1();
+ public MethodCallTest1 nullMember;
+
}
public class MethodCallTest3
}
MethodCallTest1 MethodCallTest = new MethodCallTest1();
+ MethodCallTest1 methodCallTest1Null;
+ MethodCallTest2 methodCallTest2 = new MethodCallTest2();
+ MethodCallTest2 methodCallTest2Null;
test_child TestCallChild = new test_child();
test_parent TestCallParentOverride = new test_child();
test_parent TestCallParent = new test_parent();
Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "MethodCallTest?.Calc1()", "error:");
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "6", "int", "MethodCallTest?.Calc2()");
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"VSCodeTestEvaluate.MethodCallTest1\"", "string", "MethodCallTest?.ToString()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "null", "VSCodeTestEvaluate.MethodCallTest1", "methodCallTest1Null?.Calc2()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "{System.NullReferenceException}", "System.NullReferenceException", "methodCallTest1Null.Calc2()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "null", "VSCodeTestEvaluate.MethodCallTest2", "methodCallTest2Null?.member.Calc2()");
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "methodCallTest2Null.member.Calc2()", "error:");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "{System.NullReferenceException}", "System.NullReferenceException", "methodCallTest2.nullMember.Calc2()");
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "null", "VSCodeTestEvaluate.MethodCallTest1", "methodCallTest2.nullMember?.Calc2()");
// Call non static method in static member.
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "6", "int", "VSCodeTestEvaluate.MethodCallTest2.member1.Calc2()");
{\r
class Program\r
{\r
+ public class MY\r
+ {\r
+ public int m;\r
+ public static int retme(int arg1)\r
+ {\r
+ return arg1;\r
+ }\r
+ }\r
+\r
+ public class TestNested<X,Y>\r
+ {\r
+ public class Nested<A,B>\r
+ {\r
+ public static MY my;\r
+\r
+ public A test1(A arga)\r
+ {\r
+ return arga;\r
+ }\r
+\r
+ public B test1(B argb)\r
+ {\r
+ return argb;\r
+ }\r
+\r
+ public C test3<C>(A arga, B argb, C argc)\r
+ {\r
+ return argc;\r
+ }\r
+\r
+ public static A static_test1(A arga)\r
+ {\r
+ return arga;\r
+ }\r
+\r
+ public static B static_test1(B argb)\r
+ {\r
+ return argb;\r
+ }\r
+\r
+ public static C static_test3<C>(A arga, B argb, C argc)\r
+ {\r
+ return argc;\r
+ }\r
+ }\r
+\r
+ public static Nested<X,Y> static_nested;\r
+ public Nested<X,Y> nested;\r
+ public Nested<X,Y> uninitialized;\r
+ public TestNested()\r
+ {\r
+ nested = new Nested<X,Y>();\r
+ }\r
+ }\r
+\r
public class TestGeneric<T,U>\r
{\r
+ public T test1(T argt)\r
+ {\r
+ return argt;\r
+ }\r
\r
- public T test1(T arg1)\r
+ public U test1(U argu)\r
{\r
- return arg1;\r
+ return argu;\r
}\r
\r
- public W test2<W>(W arg2)\r
+ public T test12(T argt, U argu)\r
{\r
- return arg2;\r
+ return argt;\r
}\r
\r
- static public T static_test1(T arg1)\r
+ public U test21(U argu, T argt)\r
{\r
- return arg1;\r
+ return argu;\r
+ }\r
+\r
+ public W test2<W>(W argw)\r
+ {\r
+ return argw;\r
+ }\r
+\r
+ public W test3<W>(T argt, U argu, W argw)\r
+ {\r
+ return argw;\r
}\r
\r
- static public W static_test2<W>(W arg2)\r
+ public W test41<W,Y,Z>(W argw, Y argy, Z argz, T argt)\r
{\r
- return arg2;\r
+ return argw;\r
+ }\r
+\r
+ public Y test42<W,Y,Z>(W argw, Y argy, Z argz, T argt)\r
+ {\r
+ return argy;\r
+ }\r
+\r
+ public Z test43<W,Y,Z>(W argw, Y argy, Z argz, T argt)\r
+ {\r
+ return argz;\r
+ }\r
+\r
+ public T test44<W,Y,Z>(W argw, Y argy, Z argz, T argt)\r
+ {\r
+ return argt;\r
+ }\r
+\r
+ static public T static_test1(T argt)\r
+ {\r
+ return argt;\r
+ }\r
+\r
+ static public U static_test1(U argu)\r
+ {\r
+ return argu;\r
+ }\r
+\r
+ static public W static_test2<W>(W argw)\r
+ {\r
+ return argw;\r
+ }\r
+\r
+ static public W static_test3<W>(T argt, U argu, W argw)\r
+ {\r
+ return argw;\r
+ }\r
+\r
+ static public W static_test41<W,Y,Z>(W argw, Y argy, Z argz, T argt)\r
+ {\r
+ return argw;\r
+ }\r
+\r
+ static public Y static_test42<W,Y,Z>(W argw, Y argy, Z argz, T argt)\r
+ {\r
+ return argy;\r
+ }\r
+\r
+ static public Z static_test43<W,Y,Z>(W argw, Y argy, Z argz, T argt)\r
+ {\r
+ return argz;\r
+ }\r
+\r
+ static public T static_test44<W,Y,Z>(W argw, Y argy, Z argz, T argt)\r
+ {\r
+ return argt;\r
}\r
\r
public T i1;\r
\r
public void test_func()\r
{\r
+ MY my = new MY();\r
Console.WriteLine("test_func()"); Label.Breakpoint("BREAK2");\r
\r
Label.Checkpoint("test_func", "test_set_value", (Object context) => {\r
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "456", "int", "static_p_i1");\r
Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"test_string4\"", "string", "static_p_s1");\r
\r
- // FIXME\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "5", "int", "test1(5)");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "10", "int", "test2<int>(10)");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "15", "int", "static_test1(15)");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "20", "int", "static_test2<int>(20)");\r
+ // Instance methods\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "5", "int", "test1(5)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"five\"", "string", "test1(\"five\")");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test1(false)", "error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "5", "int", "test12(5,\"five\")");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"five\"", "string", "test21(\"five\",5)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "10", "int", "test2<int>(10)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "test2<bool>(false)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "97 'a'", "char", "test2<char>('a')");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"abc\"", "string", "test2<string>(\"abc\")");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "{VSCodeTestGeneric.Program.MY}", "VSCodeTestGeneric.Program.MY", "test2<MY>(my)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "97 'a'", "char", "test3<char>(101,\"string\",'a')");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test3<bool>(101,\"string\",'a')", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test3<char>(101,'a','a')", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test3<char>('a',\"string\",'a')", "error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "97 'a'", "char", "test41<char,bool,string>('a',true,\"string\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "test42<char,bool,string>('a',true,\"string\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"string\"", "string", "test43<char,bool,string>('a',true,\"string\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "41", "int", "test44<char,bool,string>('a',true,\"string\", 41)");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test44<bool,string,char>('a',true,\"string\", 41)", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test44<string,char,bool>('a',true,\"string\", 41)", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "test44<bool,char,string>('a',true,\"string\", 41)", "error");\r
+\r
+ // Static methods\r
+\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "15", "int", "static_test1(15)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"fifteen\"", "string", "static_test1(\"fifteen\")");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "static_test1(false)", "error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "20", "int", "static_test2<int>(20)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "static_test2<bool>(true)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "120 'x'", "char", "static_test2<char>('x')");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"xyz\"", "string", "static_test2<string>(\"xyz\")");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "{VSCodeTestGeneric.Program.MY}", "VSCodeTestGeneric.Program.MY", "static_test2<MY>(my)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "97 'a'", "char", "static_test3<char>(101,\"string\",'a')");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "static_test3<bool>(101,\"string\",'a')", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "static_test3<char>(101,'a','a')", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "static_test3<char>('a',\"string\",'a')", "error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "97 'a'", "char", "static_test41<char,bool,string>('a',true,\"string\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "static_test42<char,bool,string>('a',true,\"string\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"string\"", "string", "static_test43<char,bool,string>('a',true,\"string\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "41", "int", "static_test44<char,bool,string>('a',true,\"string\", 41)");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "static_test44<bool,string,char>('a',true,\"string\", 41)", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "static_test44<string,char,bool>('a',true,\"string\", 41)", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "static_test44<bool,char,string>('a',true,\"string\", 41)", "error");\r
\r
// Test set value.\r
\r
TestGeneric<int,string>.static_s1 = "test_string3";\r
TestGeneric<int,string>.static_p_i1 = 456;\r
TestGeneric<int,string>.static_p_s1 = "test_string4";\r
+ MY my = new MY();\r
+ TestNested<char,int> testnested = new TestNested<char,int>();\r
+ TestNested<char,int> uninitialized;\r
\r
ttt.test_func(); Label.Breakpoint("BREAK1");\r
\r
Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "ttt.static_p_i1", "error");\r
Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "ttt.static_p_s1", "error");\r
\r
- // FIXME debugger must be fixed first\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "345", "int", "TestGeneric<int, string>.static_i1");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"test_string3\"", "string", "TestGeneric<int, string>.static_s1");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "456", "int", "TestGeneric<int, string>.static_p_i1");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"test_string4\"", "string", "TestGeneric<int, string>.static_p_s1");\r
-\r
- // FIXME debugger must be fixed first\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "5", "int", "ttt.test1(5)");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "10", "int", "ttt.test2<int>(10)");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "15", "int", "TestGeneric<int,string>.static_test1(15)");\r
- //Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "20", "int", "TestGeneric<int,string>.static_test2<int>(20)");\r
+ // Static members\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "345", "int", "TestGeneric<int, string>.static_i1");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"test_string3\"", "string", "TestGeneric<int, string>.static_s1");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "456", "int", "TestGeneric<int, string>.static_p_i1");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"test_string4\"", "string", "TestGeneric<int, string>.static_p_s1");\r
+\r
+ // Instance methods\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "5", "int", "ttt.test1(5)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"five\"", "string", "ttt.test1(\"five\")");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "ttt.test1(false)", "error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "5", "int", "ttt.test12(5,\"five\")");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"five\"", "string", "ttt.test21(\"five\",5)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "10", "int", "ttt.test2<int>(10)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "false", "bool", "ttt.test2<bool>(false)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "97 'a'", "char", "ttt.test2<char>('a')");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"abc\"", "string", "ttt.test2<string>(\"abc\")");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "{VSCodeTestGeneric.Program.MY}", "VSCodeTestGeneric.Program.MY", "ttt.test2<MY>(my)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "97 'a'", "char", "ttt.test3<char>(101,\"string\",'a')");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "ttt.test3<bool>(101,\"string\",'a')", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "ttt.test3<char>(101,'a','a')", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "ttt.test3<char>('a',\"string\",'a')", "error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "97 'a'", "char", "ttt.test41<char,bool,string>('a',true,\"string\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "ttt.test42<char,bool,string>('a',true,\"string\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"string\"", "string", "ttt.test43<char,bool,string>('a',true,\"string\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "41", "int", "ttt.test44<char,bool,string>('a',true,\"string\", 41)");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "ttt.test44<bool,string,char>('a',true,\"string\", 41)", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "ttt.test44<string,char,bool>('a',true,\"string\", 41)", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "ttt.test44<bool,char,string>('a',true,\"string\", 41)", "error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "97 'a'", "char", "testnested.nested.test1('a')");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "123", "int", "testnested.nested.test1(123)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "789", "int", "testnested.nested.test3<int>('c',456,789)");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "testnested.nested.test3<int>(false,456,789)", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "testnested.nested.test3<int>('c',456,\"abc\")", "error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"cde\"", "string", "testnested.nested.test3<string>('c',456,\"cde\")");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "testnested.nested.test3<string>(false,456,\"cde\")", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "testnested.nested.test3<string>('c',456,789)", "error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "null", "VSCodeTestGeneric.Program.TestNested<char, int>", "uninitialized?.uninitialized?.test3<string>('c',456,\"cde\")");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "null", "VSCodeTestGeneric.Program.TestNested<char, int>.Nested<char, int>", "testnested.uninitialized?.test3<string>('c',456,\"cde\")");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "uninitialized.uninitialized?.test3<string>('c',456,\"cde\")", "error");\r
+\r
+ // Static methods\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "15", "int", "TestGeneric<int,string>.static_test1(15)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"fifteen\"", "string", "TestGeneric<int,string>.static_test1(\"fifteen\")");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "TestGeneric<int,string>.static_test1(false)", "error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "20", "int", "TestGeneric<int,string>.static_test2<int>(20)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "TestGeneric<int,string>.static_test2<bool>(true)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "120 'x'", "char", "TestGeneric<int,string>.static_test2<char>('x')");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"xyz\"", "string", "TestGeneric<int,string>.static_test2<string>(\"xyz\")");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "{VSCodeTestGeneric.Program.MY}", "VSCodeTestGeneric.Program.MY", "TestGeneric<int,string>.static_test2<MY>(my)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "97 'a'", "char", "TestGeneric<int,string>.static_test3<char>(101,\"string\",'a')");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "TestGeneric<int,string>.static_test3<bool>(101,\"string\",'a')", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "TestGeneric<int,string>.static_test3<char>(101,'a','a')", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "TestGeneric<int,string>.static_test3<char>('a',\"string\",'a')", "error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "97 'a'", "char", "TestGeneric<int,string>.static_test41<char,bool,string>('a',true,\"string\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "TestGeneric<int,string>.static_test42<char,bool,string>('a',true,\"string\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"string\"", "string", "TestGeneric<int,string>.static_test43<char,bool,string>('a',true,\"string\", 41)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "41", "int", "TestGeneric<int,string>.static_test44<char,bool,string>('a',true,\"string\", 41)");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "TestGeneric<int,string>.static_test44<bool,string,char>('a',true,\"string\", 41)", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "TestGeneric<int,string>.static_test44<string,char,bool>('a',true,\"string\", 41)", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "TestGeneric<int,string>.static_test44<bool,char,string>('a',true,\"string\", 41)", "error");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "97 'a'", "char", "TestNested<int,string>.Nested<char,bool>.static_test1('a')");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "true", "bool", "TestNested<int,string>.Nested<char,bool>.static_test1(true)");\r
+ Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "\"abc\"", "string", "TestNested<int,string>.Nested<char,bool>.static_test3<string>('a', true, \"abc\")");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "TestNested<int,string>.Nested<char,bool>.static_test1(\"xyz\")", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "TestNested<int,string>.Nested<char,bool>.static_test3<string>('a', true, 123)", "error");\r
+ Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "TestNested<int,string>.Nested<char,bool>.static_test3<string>(123, true, \"abc\")", "error");\r
\r
Context.Continue(@"__FILE__:__LINE__");\r
});\r
Context.SetVariable(@"__FILE__:__LINE__", frameId, setStaticReference, "static_p_s1", "\"changed_string44\"");\r
\r
// FIXME debugger must be fixed first\r
- //Context.SetExpression(@"__FILE__:__LINE__", frameId, "TestGeneric<int,string>.static_i1", "777");\r
- //Context.SetExpression(@"__FILE__:__LINE__", frameId, "TestGeneric<int,string>.static_s1", "\"changed_string3\"");\r
+ Context.SetExpression(@"__FILE__:__LINE__", frameId, "TestGeneric<int,string>.static_i1", "777");\r
+ Context.SetExpression(@"__FILE__:__LINE__", frameId, "TestGeneric<int,string>.static_s1", "\"changed_string3\"");\r
\r
// FIXME debugger must be fixed first\r
- //Context.SetExpression(@"__FILE__:__LINE__", frameId, "TestGeneric<int,string>.static_p_i1", "888");\r
- //Context.SetExpression(@"__FILE__:__LINE__", frameId, "TestGeneric<int,string>.static_p_s1", "\"changed_string4\"");\r
+ Context.SetExpression(@"__FILE__:__LINE__", frameId, "TestGeneric<int,string>.static_p_i1", "888");\r
+ Context.SetExpression(@"__FILE__:__LINE__", frameId, "TestGeneric<int,string>.static_p_s1", "\"changed_string4\"");\r
\r
Context.Continue(@"__FILE__:__LINE__");\r
});\r