public ScriptCSharpGenerator(ScenarioTag scnr, MemberNameRepository nameRepo, string[] refrences = null, AttributeSyntax[] classAttributes = null) { this.scenario = scnr; this.nameRepo = nameRepo; var scenarioParts = scnr.Name.Split('\\', StringSplitOptions.RemoveEmptyEntries); var ns = "OpenH2.Scripts.Generated" + string.Join(".", scenarioParts.Take(2)); this.nsDecl = NamespaceDeclaration(ParseName(ns)); var classModifiers = SyntaxTokenList.Create(Token(SyntaxKind.PublicKeyword)) .Add(Token(SyntaxKind.PartialKeyword)); this.classDecl = ClassDeclaration("scnr_" + scenarioParts.Last()) .WithModifiers(classModifiers); if (classAttributes != null && classAttributes.Any()) { var classAttrs = List <AttributeListSyntax>() .Add(AttributeList(SeparatedList(classAttributes))); this.classDecl = this.classDecl.WithAttributeLists(classAttrs); } }
public void Load(ScenarioTag scnr) { var scenarioParts = scnr.Name.Split('\\', StringSplitOptions.RemoveEmptyEntries) .Select(p => p.Trim()) .ToArray(); var repo = new MemberNameRepository(); // Reserve class field and method names for (var i = 0; i < scnr.ScriptVariables.Length; i++) { var variable = scnr.ScriptVariables[i]; var returnedName = repo.RegisterName(variable.Description, variable.DataType.ToString(), i); } for (var i = 0; i < scnr.ScriptMethods.Length; i++) { var method = scnr.ScriptMethods[i]; var returnedName = repo.RegisterName(method.Description, ScriptDataType.ScriptReference.ToString(), i); } var baseFields = typeof(ScenarioScriptBase).GetFields(); foreach (var field in baseFields) { var found = SyntaxUtil.TryGetScriptTypeFromType(field.FieldType, out var t); Debug.Assert(found); repo.RegisterName(field.Name, t.ToString()); } // Generate data properties var dataGen = new ScriptCSharpGenerator(scnr, repo); dataGen.AddProperties(scnr); dataGen.CreateDataInitializer(scnr); var originAttr = SyntaxFactory.Attribute( SyntaxFactory.ParseName("OriginScenario"), SyntaxFactory.AttributeArgumentList(SyntaxFactory.SeparatedList(new[] { SyntaxFactory.AttributeArgument( SyntaxFactory.LiteralExpression( SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(scnr.Name))) }))); var classGen = new ScriptCSharpGenerator(scnr, repo, classAttributes: new[] { originAttr }); foreach (var variable in scnr.ScriptVariables) { classGen.AddGlobalVariable(variable); } for (int i = 0; i < scnr.ScriptMethods.Length; i++) { classGen.AddMethod(i, scnr.ScriptMethods[i]); } this.AddCode($"{scenarioParts.Last()}.cs", classGen.Generate()); this.AddCode($"{scenarioParts.Last()}.Data.cs", dataGen.Generate()); }
// Make squads into nested classes public void CreateNestedSquadClasses(ScenarioTag tag) { for (var i = 0; i < tag.AiSquadDefinitions.Length; i++) { var squad = tag.AiSquadDefinitions[i]; var squadPropName = nameRepo.RegisterName(squad.Description, ScriptDataType.AI.ToString(), i); var dataClassProps = new List <PropertyDeclarationSyntax>(); dataClassProps.Add(SyntaxUtil.CreateProperty(ParseTypeName(nameof(ScenarioTag)), nameof(ScenarioTag))); var nestedRepo = new MemberNameRepository(); var m = 0; foreach (var ai in squad.StartingLocations) { var propName = nestedRepo.RegisterName(ai.Description, ScriptDataType.AI.ToString(), m); ExpressionSyntax startingLocationAccess = ElementAccessExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ElementAccessExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(ScenarioTag)), IdentifierName(nameof(tag.AiSquadDefinitions)))) .AddArgumentListArguments(Argument(SyntaxUtil.LiteralExpression(i))), IdentifierName(nameof(squad.StartingLocations)))) .AddArgumentListArguments(Argument(SyntaxUtil.LiteralExpression(m))); dataClassProps.Add(PropertyDeclaration(SyntaxUtil.ScriptTypeSyntax(ScriptDataType.AI), propName) .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) .WithExpressionBody(ArrowExpressionClause(startingLocationAccess)) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))); m++; } ExpressionSyntax squadAccess = ElementAccessExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(ScenarioTag)), IdentifierName(nameof(tag.AiSquadDefinitions)))) .AddArgumentListArguments(Argument(SyntaxUtil.LiteralExpression(i))); // This is so the script can reference the squad itself, need special init handling dataClassProps.Add(PropertyDeclaration(SyntaxUtil.ScriptTypeSyntax(ScriptDataType.AI), "Squad") .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) .WithExpressionBody(ArrowExpressionClause(squadAccess)) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))); var squadTypeName = "Squad_" + squadPropName; var cls = ClassDeclaration(squadTypeName) .AddModifiers(Token(SyntaxKind.PublicKeyword)) .WithMembers(new SyntaxList <MemberDeclarationSyntax>(dataClassProps)) .AddMembers(ConstructorDeclaration(squadTypeName) .AddModifiers(Token(SyntaxKind.PublicKeyword)) .AddParameterListParameters( Parameter(Identifier(nameof(ScenarioTag))) .WithType(ParseTypeName(nameof(ScenarioTag)))) .WithBody(Block(new List <StatementSyntax>() { ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName(nameof(ScenarioTag))), IdentifierName(nameof(ScenarioTag)))) }))); nestedDataClasses.Add(cls); nameRepo.NestedRepos.Add(squadPropName, nestedRepo); properties.Add(PropertyDeclaration(ParseTypeName(squadTypeName), squadPropName) .AddModifiers(Token(SyntaxKind.PublicKeyword)) .WithAccessorList(SyntaxUtil.AutoPropertyAccessorList())); } }