mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 00:02:55 +00:00
ZoneCodeGenerator: Add Evaluation as basis for specifying conditions and counts
This commit is contained in:
parent
61eb92588e
commit
785e2c9bfb
15
src/ZoneCodeGenerator/Domain/Evaluation/IEvaluation.cs
Normal file
15
src/ZoneCodeGenerator/Domain/Evaluation/IEvaluation.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ZoneCodeGenerator.Domain.Evaluation
|
||||||
|
{
|
||||||
|
interface IEvaluation
|
||||||
|
{
|
||||||
|
bool IsStatic { get; }
|
||||||
|
|
||||||
|
int EvaluateNumeric();
|
||||||
|
}
|
||||||
|
}
|
17
src/ZoneCodeGenerator/Domain/Evaluation/OperandDynamic.cs
Normal file
17
src/ZoneCodeGenerator/Domain/Evaluation/OperandDynamic.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ZoneCodeGenerator.Domain.Evaluation
|
||||||
|
{
|
||||||
|
class OperandDynamic : IEvaluation
|
||||||
|
{
|
||||||
|
public bool IsStatic => false;
|
||||||
|
public int EvaluateNumeric()
|
||||||
|
{
|
||||||
|
throw new Exception("A dynamic operand cannot be evaluated.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
src/ZoneCodeGenerator/Domain/Evaluation/OperandStatic.cs
Normal file
24
src/ZoneCodeGenerator/Domain/Evaluation/OperandStatic.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ZoneCodeGenerator.Domain.Evaluation
|
||||||
|
{
|
||||||
|
class OperandStatic : IEvaluation
|
||||||
|
{
|
||||||
|
public int Value { get; }
|
||||||
|
|
||||||
|
public bool IsStatic => true;
|
||||||
|
public int EvaluateNumeric()
|
||||||
|
{
|
||||||
|
return Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperandStatic(int value)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
src/ZoneCodeGenerator/Domain/Evaluation/Operation.cs
Normal file
29
src/ZoneCodeGenerator/Domain/Evaluation/Operation.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ZoneCodeGenerator.Domain.Evaluation
|
||||||
|
{
|
||||||
|
class Operation : IEvaluation
|
||||||
|
{
|
||||||
|
public IEvaluation Operand1 { get; }
|
||||||
|
public IEvaluation Operand2 { get; }
|
||||||
|
public OperationType OperationType { get; }
|
||||||
|
|
||||||
|
public bool IsStatic => Operand1.IsStatic && Operand2.IsStatic;
|
||||||
|
|
||||||
|
public int EvaluateNumeric()
|
||||||
|
{
|
||||||
|
return OperationType.Function(Operand1.EvaluateNumeric(), Operand2.EvaluateNumeric());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operation(IEvaluation operand1, IEvaluation operand2, OperationType type)
|
||||||
|
{
|
||||||
|
Operand1 = operand1;
|
||||||
|
Operand2 = operand2;
|
||||||
|
OperationType = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
138
src/ZoneCodeGenerator/Domain/Evaluation/OperationType.cs
Normal file
138
src/ZoneCodeGenerator/Domain/Evaluation/OperationType.cs
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ZoneCodeGenerator.Domain.Evaluation
|
||||||
|
{
|
||||||
|
sealed class OperationType
|
||||||
|
{
|
||||||
|
// https://en.cppreference.com/w/cpp/language/operator_precedence
|
||||||
|
public enum OperationPrecedence
|
||||||
|
{
|
||||||
|
MultiplicationDivisionRemainder = 1,
|
||||||
|
AdditionSubtraction = 2,
|
||||||
|
BitwiseShift = 3,
|
||||||
|
RelationalGreaterLessThan = 4,
|
||||||
|
RelationalEquals = 5,
|
||||||
|
LogicalAnd = 6,
|
||||||
|
LogicalOr = 7
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate int EvaluationFunction(int operand1, int operand2);
|
||||||
|
|
||||||
|
public string Syntax { get; }
|
||||||
|
public OperationPrecedence Precedence { get; }
|
||||||
|
public EvaluationFunction Function { get; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Syntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OperationType(string syntax, OperationPrecedence precedence, EvaluationFunction function)
|
||||||
|
{
|
||||||
|
Syntax = syntax;
|
||||||
|
Precedence = precedence;
|
||||||
|
Function = function;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OperationType OperationAdd = new OperationType(
|
||||||
|
"+",
|
||||||
|
OperationPrecedence.AdditionSubtraction,
|
||||||
|
(operand1, operand2) => operand1 + operand2
|
||||||
|
);
|
||||||
|
|
||||||
|
public static OperationType OperationSubtract = new OperationType(
|
||||||
|
"-",
|
||||||
|
OperationPrecedence.AdditionSubtraction,
|
||||||
|
(operand1, operand2) => operand1 - operand2
|
||||||
|
);
|
||||||
|
|
||||||
|
public static OperationType OperationMultiply = new OperationType(
|
||||||
|
"*",
|
||||||
|
OperationPrecedence.MultiplicationDivisionRemainder,
|
||||||
|
(operand1, operand2) => operand1 * operand2
|
||||||
|
);
|
||||||
|
|
||||||
|
public static OperationType OperationDivide = new OperationType(
|
||||||
|
"/",
|
||||||
|
OperationPrecedence.MultiplicationDivisionRemainder,
|
||||||
|
(operand1, operand2) => operand1 / operand2
|
||||||
|
);
|
||||||
|
|
||||||
|
public static OperationType OperationRemainder = new OperationType(
|
||||||
|
"%",
|
||||||
|
OperationPrecedence.MultiplicationDivisionRemainder,
|
||||||
|
(operand1, operand2) => operand1 % operand2
|
||||||
|
);
|
||||||
|
|
||||||
|
public static OperationType OperationShiftLeft = new OperationType(
|
||||||
|
"<<",
|
||||||
|
OperationPrecedence.BitwiseShift,
|
||||||
|
(operand1, operand2) => operand1 << operand2
|
||||||
|
);
|
||||||
|
|
||||||
|
public static OperationType OperationShiftRight = new OperationType(
|
||||||
|
">>",
|
||||||
|
OperationPrecedence.BitwiseShift,
|
||||||
|
(operand1, operand2) => operand1 >> operand2
|
||||||
|
);
|
||||||
|
|
||||||
|
public static OperationType OperationGreaterThan = new OperationType(
|
||||||
|
">",
|
||||||
|
OperationPrecedence.RelationalGreaterLessThan,
|
||||||
|
(operand1, operand2) => operand1 > operand2 ? 1 : 0
|
||||||
|
);
|
||||||
|
|
||||||
|
public static OperationType OperationGreaterEqualsThan = new OperationType(
|
||||||
|
">=",
|
||||||
|
OperationPrecedence.RelationalGreaterLessThan,
|
||||||
|
(operand1, operand2) => operand1 >= operand2 ? 1 : 0
|
||||||
|
);
|
||||||
|
|
||||||
|
public static OperationType OperationLessThan = new OperationType(
|
||||||
|
"<",
|
||||||
|
OperationPrecedence.RelationalGreaterLessThan,
|
||||||
|
(operand1, operand2) => operand1 < operand2 ? 1 : 0
|
||||||
|
);
|
||||||
|
|
||||||
|
public static OperationType OperationLessEqualsThan = new OperationType(
|
||||||
|
"<=",
|
||||||
|
OperationPrecedence.RelationalGreaterLessThan,
|
||||||
|
(operand1, operand2) => operand1 <= operand2 ? 1 : 0
|
||||||
|
);
|
||||||
|
|
||||||
|
public static OperationType OperationEquals = new OperationType(
|
||||||
|
"==",
|
||||||
|
OperationPrecedence.RelationalEquals,
|
||||||
|
(operand1, operand2) => operand1 == operand2 ? 1 : 0
|
||||||
|
);
|
||||||
|
|
||||||
|
public static OperationType OperationNotEquals = new OperationType(
|
||||||
|
"!=",
|
||||||
|
OperationPrecedence.RelationalEquals,
|
||||||
|
(operand1, operand2) => operand1 != operand2 ? 1 : 0
|
||||||
|
);
|
||||||
|
|
||||||
|
public static OperationType OperationAnd = new OperationType(
|
||||||
|
"&&",
|
||||||
|
OperationPrecedence.LogicalAnd,
|
||||||
|
(operand1, operand2) => operand1 > 0 && operand2 > 0 ? 1 : 0
|
||||||
|
);
|
||||||
|
|
||||||
|
public static OperationType OperationOr = new OperationType(
|
||||||
|
"||",
|
||||||
|
OperationPrecedence.LogicalOr,
|
||||||
|
(operand1, operand2) => operand1 > 0 || operand2 > 0 ? 1 : 0
|
||||||
|
);
|
||||||
|
|
||||||
|
public static List<OperationType> Types => typeof(OperationType)
|
||||||
|
.GetFields(BindingFlags.Static | BindingFlags.Public)
|
||||||
|
.Select(info => info.GetValue(null))
|
||||||
|
.OfType<OperationType>()
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,14 @@
|
|||||||
namespace ZoneCodeGenerator.Domain
|
using System;
|
||||||
|
using ZoneCodeGenerator.Domain.Evaluation;
|
||||||
|
|
||||||
|
namespace ZoneCodeGenerator.Domain
|
||||||
{
|
{
|
||||||
class ReferenceTypePointer : ReferenceType
|
class ReferenceTypePointer : ReferenceType
|
||||||
{
|
{
|
||||||
|
public static IEvaluation DefaultCount = new OperandStatic(1);
|
||||||
|
|
||||||
|
public IEvaluation Count { get; set; } = DefaultCount;
|
||||||
|
|
||||||
|
public bool IsArray => !Count.IsStatic || Count.EvaluateNumeric() > 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,8 @@ namespace ZoneCodeGenerator.Domain.StructureInformation
|
|||||||
public List<StructureInformation> Usages { get; }
|
public List<StructureInformation> Usages { get; }
|
||||||
public List<MemberInformation> OrderedMembers { get; }
|
public List<MemberInformation> OrderedMembers { get; }
|
||||||
public bool NonEmbeddedReferenceExists { get; set; }
|
public bool NonEmbeddedReferenceExists { get; set; }
|
||||||
public bool PointerReferenceExists { get; set; }
|
public bool SinglePointerReferenceExists { get; set; }
|
||||||
|
public bool ArrayPointerReferenceExists { get; set; }
|
||||||
public bool ArrayReferenceExists { get; set; }
|
public bool ArrayReferenceExists { get; set; }
|
||||||
|
|
||||||
public bool HasNameMember => Type.Members.Any(variable => variable.Name.Equals("name", StringComparison.CurrentCultureIgnoreCase));
|
public bool HasNameMember => Type.Members.Any(variable => variable.Name.Equals("name", StringComparison.CurrentCultureIgnoreCase));
|
||||||
@ -37,7 +38,7 @@ namespace ZoneCodeGenerator.Domain.StructureInformation
|
|||||||
fastFileAlign = null;
|
fastFileAlign = null;
|
||||||
Type = type;
|
Type = type;
|
||||||
NonEmbeddedReferenceExists = false;
|
NonEmbeddedReferenceExists = false;
|
||||||
PointerReferenceExists = false;
|
SinglePointerReferenceExists = false;
|
||||||
ArrayReferenceExists = false;
|
ArrayReferenceExists = false;
|
||||||
Usages = new List<StructureInformation>();
|
Usages = new List<StructureInformation>();
|
||||||
OrderedMembers = new List<MemberInformation>();
|
OrderedMembers = new List<MemberInformation>();
|
||||||
|
@ -9,21 +9,21 @@ LoaderClassName(asset) ::= "Loader_$asset.Type.Name$"
|
|||||||
|
|
||||||
HeaderConstructor(context) ::= "$LoaderClassName(context.Asset)$(IZoneScriptStringProvider* scriptStringProvider, Zone* zone, IZoneInputStream* stream);"
|
HeaderConstructor(context) ::= "$LoaderClassName(context.Asset)$(IZoneScriptStringProvider* scriptStringProvider, Zone* zone, IZoneInputStream* stream);"
|
||||||
|
|
||||||
HeaderPtrLoadMethodDeclaration(structure) ::= "void LoadPtr_$structure.Type.Name$($structure.Type.FullName$** pPtr);"
|
HeaderSinglePtrLoadMethodDeclaration(structure) ::= "void LoadPtr_$structure.Type.Name$($structure.Type.FullName$** pPtr);"
|
||||||
HeaderArrayLoadMethodDeclaration(structure) ::= "void LoadArray_$structure.Type.Name$($structure.Type.FullName$** pArray, size_t count, bool atStreamStart);"
|
HeaderArrayPtrLoadMethodDeclaration(structure) ::= "void LoadArray_$structure.Type.Name$($structure.Type.FullName$** pArray, size_t count, bool atStreamStart);"
|
||||||
HeaderLoadMethodDeclaration(structure) ::= "void Load_$structure.Type.Name$($structure.Type.FullName$* p$structure.Type.Name$, bool atStreamStart);"
|
HeaderLoadMethodDeclaration(structure) ::= "void Load_$structure.Type.Name$($structure.Type.FullName$* p$structure.Type.Name$, bool atStreamStart);"
|
||||||
|
|
||||||
HeaderGetNameMethodDeclaration(asset) ::= "static std::string GetAssetName($asset.Type.FullName$* p$asset.Type.Name$);"
|
HeaderGetNameMethodDeclaration(asset) ::= "static std::string GetAssetName($asset.Type.FullName$* p$asset.Type.Name$);"
|
||||||
HeaderAssetLoadMethodDeclaration(asset) ::= "void LoadAsset_$asset.Type.Name$($asset.Type.FullName$** pPtr);"
|
HeaderAssetLoadMethodDeclaration(asset) ::= "void LoadAsset_$asset.Type.Name$($asset.Type.FullName$** pPtr);"
|
||||||
|
|
||||||
HeaderDeclaration(structure) ::= <%
|
HeaderDeclaration(structure) ::= <%
|
||||||
$if(structure.PointerReferenceExists)$
|
$if(structure.SinglePointerReferenceExists)$
|
||||||
$HeaderPtrLoadMethodDeclaration(structure)$
|
$HeaderSinglePtrLoadMethodDeclaration(structure)$
|
||||||
$\n$
|
$\n$
|
||||||
$endif$
|
$endif$
|
||||||
|
|
||||||
$if(structure.ArrayReferenceExists)$
|
$if(structure.ArrayPointerReferenceExists)$
|
||||||
$HeaderArrayLoadMethodDeclaration(structure)$
|
$HeaderArrayPtrLoadMethodDeclaration(structure)$
|
||||||
$\n$
|
$\n$
|
||||||
$endif$
|
$endif$
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ namespace $context.Game$
|
|||||||
public:
|
public:
|
||||||
$HeaderConstructor(context)$
|
$HeaderConstructor(context)$
|
||||||
|
|
||||||
$HeaderPtrLoadMethodDeclaration(context.Asset)$
|
$HeaderSinglePtrLoadMethodDeclaration(context.Asset)$
|
||||||
$HeaderGetNameMethodDeclaration(context.Asset)$
|
$HeaderGetNameMethodDeclaration(context.Asset)$
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@ void $LoaderClassName(context.Asset)$::Load_$structure.Type.Name$($structure.Typ
|
|||||||
}
|
}
|
||||||
>>
|
>>
|
||||||
|
|
||||||
LoadPtrMethod(structure, context) ::= <<
|
LoadSinglePtrMethod(structure, context) ::= <<
|
||||||
void $LoaderClassName(context.Asset)$::LoadPtr_$structure.Type.Name$($structure.Type.FullName$** pPtr)
|
void $LoaderClassName(context.Asset)$::LoadPtr_$structure.Type.Name$($structure.Type.FullName$** pPtr)
|
||||||
{
|
{
|
||||||
assert(pPtr != nullptr);
|
assert(pPtr != nullptr);
|
||||||
@ -141,7 +141,7 @@ void $LoaderClassName(context.Asset)$::LoadPtr_$structure.Type.Name$($structure.
|
|||||||
}
|
}
|
||||||
>>
|
>>
|
||||||
|
|
||||||
LoadArrayMethod(structure, context) ::= <<
|
LoadArrayPtrMethod(structure, context) ::= <<
|
||||||
void $LoaderClassName(context.Asset)$::LoadArray_$structure.Type.Name$($structure.Type.FullName$** pArray, const size_t count, const bool atStreamStart)
|
void $LoaderClassName(context.Asset)$::LoadArray_$structure.Type.Name$($structure.Type.FullName$** pArray, const size_t count, const bool atStreamStart)
|
||||||
{
|
{
|
||||||
assert(pArray != nullptr);
|
assert(pArray != nullptr);
|
||||||
@ -161,12 +161,12 @@ $if(structure.NonEmbeddedReferenceExists)$
|
|||||||
$LoadMethod(structure, context)$
|
$LoadMethod(structure, context)$
|
||||||
|
|
||||||
$endif$
|
$endif$
|
||||||
$if(structure.PointerReferenceExists)$
|
$if(structure.SinglePointerReferenceExists)$
|
||||||
$LoadPtrMethod(structure, context)$
|
$LoadSinglePtrMethod(structure, context)$
|
||||||
|
|
||||||
$endif$
|
$endif$
|
||||||
$if(structure.ArrayReferenceExists)$
|
$if(structure.ArrayPointerReferenceExists)$
|
||||||
$LoadArrayMethod(structure, context)$
|
$LoadArrayPtrMethod(structure, context)$
|
||||||
|
|
||||||
$endif$
|
$endif$
|
||||||
>>
|
>>
|
||||||
@ -220,7 +220,7 @@ $LoadMethod(context.Asset, context)$
|
|||||||
|
|
||||||
$LoadAssetMethod(context.Asset, context)$
|
$LoadAssetMethod(context.Asset, context)$
|
||||||
|
|
||||||
$LoadPtrMethod(context.Asset, context)$
|
$LoadSinglePtrMethod(context.Asset, context)$
|
||||||
|
|
||||||
$GetNameMethod(context)$
|
$GetNameMethod(context)$
|
||||||
>>
|
>>
|
@ -23,11 +23,14 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor
|
|||||||
if (IsNonEmbeddedReference(memberInformation.Member))
|
if (IsNonEmbeddedReference(memberInformation.Member))
|
||||||
memberInformation.StructureType.NonEmbeddedReferenceExists = true;
|
memberInformation.StructureType.NonEmbeddedReferenceExists = true;
|
||||||
|
|
||||||
if (IsPointerReference(memberInformation.Member))
|
if (IsSinglePointerReference(memberInformation.Member))
|
||||||
memberInformation.StructureType.PointerReferenceExists = true;
|
memberInformation.StructureType.SinglePointerReferenceExists = true;
|
||||||
|
|
||||||
|
if (IsArrayPointerReference(memberInformation.Member))
|
||||||
|
memberInformation.StructureType.ArrayPointerReferenceExists = true;
|
||||||
|
|
||||||
if (IsArrayReference(memberInformation.Member))
|
if (IsArrayReference(memberInformation.Member))
|
||||||
memberInformation.StructureType.PointerReferenceExists = true;
|
memberInformation.StructureType.ArrayReferenceExists = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,10 +42,18 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor
|
|||||||
return var.VariableType.References.Any();
|
return var.VariableType.References.Any();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsPointerReference(Variable var)
|
private static bool IsSinglePointerReference(Variable var)
|
||||||
{
|
{
|
||||||
return var.VariableType.References.Any()
|
return var.VariableType.References.Any()
|
||||||
&& var.VariableType.References.Last() is ReferenceTypePointer;
|
&& var.VariableType.References.Last() is ReferenceTypePointer pointerReference
|
||||||
|
&& !pointerReference.IsArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsArrayPointerReference(Variable var)
|
||||||
|
{
|
||||||
|
return var.VariableType.References.Any()
|
||||||
|
&& var.VariableType.References.Last() is ReferenceTypePointer pointerReference
|
||||||
|
&& pointerReference.IsArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsArrayReference(Variable var)
|
private static bool IsArrayReference(Variable var)
|
||||||
|
@ -63,6 +63,11 @@
|
|||||||
<Compile Include="Domain\DataTypeUnion.cs" />
|
<Compile Include="Domain\DataTypeUnion.cs" />
|
||||||
<Compile Include="Domain\DataTypeWithMembers.cs" />
|
<Compile Include="Domain\DataTypeWithMembers.cs" />
|
||||||
<Compile Include="Domain\EnumMember.cs" />
|
<Compile Include="Domain\EnumMember.cs" />
|
||||||
|
<Compile Include="Domain\Evaluation\IEvaluation.cs" />
|
||||||
|
<Compile Include="Domain\Evaluation\OperandDynamic.cs" />
|
||||||
|
<Compile Include="Domain\Evaluation\OperandStatic.cs" />
|
||||||
|
<Compile Include="Domain\Evaluation\Operation.cs" />
|
||||||
|
<Compile Include="Domain\Evaluation\OperationType.cs" />
|
||||||
<Compile Include="Domain\FastFileStructure\FastFileBlock.cs" />
|
<Compile Include="Domain\FastFileStructure\FastFileBlock.cs" />
|
||||||
<Compile Include="Domain\ForwardDeclaration.cs" />
|
<Compile Include="Domain\ForwardDeclaration.cs" />
|
||||||
<Compile Include="Domain\Namespace.cs" />
|
<Compile Include="Domain\Namespace.cs" />
|
||||||
@ -169,5 +174,6 @@
|
|||||||
<EmbeddedResource Include="Generating\Templates\AssetStructTests.stg" />
|
<EmbeddedResource Include="Generating\Templates\AssetStructTests.stg" />
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup />
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
Loading…
x
Reference in New Issue
Block a user