private void GenerateProxyMethodModifiers(CodeBuilder code) { // modifiers code.AddHeader("\t"); if (_methodInfo.CodeGenProps.AccessLevel == AccessLevel.CopyExisting) { code.AddHeader(_methodInfo.MethodSyntax.Modifiers.ToFullString().Trim()); } else { code.AddHeader(_methodInfo.CodeGenProps.GetAccessLevelModifierString() + " "); foreach (var modifier in _methodInfo.MethodSyntax.Modifiers) { switch (modifier.Kind()) { case SyntaxKind.PublicKeyword: case SyntaxKind.PrivateKeyword: case SyntaxKind.ProtectedKeyword: case SyntaxKind.InternalKeyword: // do not copy access modifiers break; default: code.AddHeader(modifier + " "); break; } } } }
/// <summary> /// Create cil source-code representation of a <see cref="EnumDefinition"/>. /// </summary> /// <exception cref="Exceptions.InvalidAssemblyNameException"> /// Thrown when a invalid assembly name is given. /// </exception> /// <exception cref="Exceptions.InvalidNamespaceException"> /// Thrown when a invalid namespace identifier is given. /// </exception> /// <exception cref="Exceptions.OutOfBoundsValueException"> /// Thrown when enum value does not fit in given storage-type. /// </exception> /// <param name="enumDefinition">Enum to generate cil source-code for</param> /// <param name="assemblyName">Name of the assembly to generate</param> /// <param name="namespace">Optional namespace to add the enum to</param> /// <param name="headerMode">Mode to use when adding a header</param> /// <param name="indentMode">Mode to use for indenting</param> /// <param name="spaceIndentSize">When indenting with spaces this controls how many</param> /// <param name="newlineMode">Mode to use for ending lines</param> /// <param name="storageType">Underlying enum storage-type to use</param> /// <param name="curlyBracketMode">Mode to use when writing curly brackets</param> /// <returns>String containing the genenerated cil sourcecode</returns> public static string ExportCil( this EnumDefinition enumDefinition, string assemblyName, string @namespace = null, HeaderMode headerMode = HeaderMode.Default, CodeBuilder.IndentMode indentMode = CodeBuilder.IndentMode.Spaces, int spaceIndentSize = 4, CodeBuilder.NewlineMode newlineMode = CodeBuilder.NewlineMode.Unix, StorageType storageType = StorageType.Implicit, CurlyBracketMode curlyBracketMode = CurlyBracketMode.NewLine) { if (enumDefinition == null) { throw new ArgumentNullException(nameof(enumDefinition)); } if (string.IsNullOrEmpty(assemblyName) || !IdentifierValidator.Validate(assemblyName)) { throw new InvalidAssemblyNameException(assemblyName); } if (!string.IsNullOrEmpty(@namespace) && !IdentifierValidator.ValidateNamespace(@namespace)) { throw new InvalidNamespaceException(@namespace); } foreach (var oobEntry in enumDefinition.Entries.Where(e => !storageType.Validate(e.Value))) { throw new OutOfBoundsValueException(storageType, oobEntry.Value); } var builder = new CodeBuilder(indentMode, spaceIndentSize, newlineMode); if (headerMode != HeaderMode.None) { builder.AddHeader(); builder.WriteEndLine(); } // Add reference to mscorlib. builder.WriteLine(".assembly extern mscorlib { }"); builder.WriteEndLine(); // Add assembly info. builder.Write($".assembly {assemblyName}"); StartScope(builder, curlyBracketMode); builder.WriteLine(".ver 1:0:0:0"); EndScope(builder); builder.WriteEndLine(); // Add module info. builder.WriteLine($".module {assemblyName}.dll"); builder.WriteEndLine(); // Add enum class. builder.AddEnum(enumDefinition, storageType, curlyBracketMode, @namespace); return(builder.Build()); }
/// <summary> /// Create csharp source-code representation of a <see cref="EnumDefinition"/>. /// </summary> /// <exception cref="Exceptions.InvalidNamespaceException"> /// Thrown when a invalid namespace identifier is given. /// </exception> /// <exception cref="Exceptions.OutOfBoundsValueException"> /// Thrown when enum value does not fit in given storage-type. /// </exception> /// <param name="enumDefinition">Enum to generate csharp source-code for</param> /// <param name="namespace">Optional namespace to add the enum to</param> /// <param name="headerMode">Mode to use when adding a header</param> /// <param name="indentMode">Mode to use for indenting</param> /// <param name="spaceIndentSize">When indenting with spaces this controls how many</param> /// <param name="newlineMode">Mode to use for ending lines</param> /// <param name="storageType">Underlying enum storage-type to use</param> /// <param name="curlyBracketMode">Mode to use when writing curly brackets</param> /// <returns>String containing the genenerated csharp sourcecode</returns> public static string ExportCSharp( this EnumDefinition enumDefinition, string @namespace = null, HeaderMode headerMode = HeaderMode.Default, CodeBuilder.IndentMode indentMode = CodeBuilder.IndentMode.Spaces, int spaceIndentSize = 4, CodeBuilder.NewlineMode newlineMode = CodeBuilder.NewlineMode.Unix, StorageType storageType = StorageType.Implicit, CurlyBracketMode curlyBracketMode = CurlyBracketMode.NewLine) { if (enumDefinition == null) { throw new ArgumentNullException(nameof(enumDefinition)); } if (!string.IsNullOrEmpty(@namespace) && !IdentifierValidator.ValidateNamespace(@namespace)) { throw new InvalidNamespaceException(@namespace); } foreach (var oobEntry in enumDefinition.Entries.Where(e => !storageType.Validate(e.Value))) { throw new OutOfBoundsValueException(storageType, oobEntry.Value); } var builder = new CodeBuilder(indentMode, spaceIndentSize, newlineMode); if (headerMode != HeaderMode.None) { builder.AddHeader(); builder.WriteEndLine(); } builder.WriteLine("using System.CodeDom.Compiler;"); builder.WriteEndLine(); if (string.IsNullOrEmpty(@namespace)) { builder.AddEnum(enumDefinition, storageType, curlyBracketMode); } else { builder.AddNamespace( @namespace, b => b.AddEnum(enumDefinition, storageType, curlyBracketMode), curlyBracketMode); } return(builder.Build()); }
private void GenerateProxyMethodBody(CodeBuilder code) { // method body code.AddBlockHeader("\t"); // create the initial CallParams struct code.AddHeader($"\t\tvar {ParamsVarName} = new {_methodInfo.MethodParamsStructName}{_methodInfo.GenericParams} (") .AddHeader(string.Join(", ", _methodInfo.MethodSyntax.ParameterList.Parameters.Select(parameterSyntax => _methodInfo.MethodModel.GetDeclaredSymbol(parameterSyntax).Name))) .AddHeaderLine(");"); code.AddHeaderLine($"\t\tvar runner = new {_calculatorClassInfo.CalculatorClassName}{_calculatorClassInfo.GenericParams}();"); code.AddHeaderLine($"\t\trunner.RunRecursion({ParamsVarName});"); if (_methodInfo.ShouldGenerateReturnField) { code.AddHeaderLine($"\t\treturn runner.{_methodInfo.ReturnFieldName};"); } }
private void GenerateProxyMethodSignature(CodeBuilder code) { code.AddHeader(" "); code.AddHeader(_methodInfo.ReturnType); code.AddHeader(_methodInfo.MethodName); code.AddHeader(_methodInfo.GenericParams); code.AddHeader(GetProxyMethodParamsList().ToFullString()); if (!string.IsNullOrEmpty(_methodInfo.ConstraintClauses)) { code.AddHeader("\t\t"); code.AddHeaderLine(_methodInfo.ConstraintClauses); } }
internal string GenerateCalculatorMethodBody(TargetMethodsInfo targetMethods) { var code = new CodeBuilder(); // unpack params code.AddHeaderLine("\t\t// unpack params"); code.AddHeaderLine(string.Join("\n", _methodInfo.MethodSyntax.ParameterList.Parameters.Select(parameterSyntax => { var paramSymbol = _methodInfo.MethodModel.GetDeclaredSymbol(parameterSyntax); return($"\t\tvar {paramSymbol.Name} = {ParamsVarName}.{paramSymbol.Name};"); }))); // find all recursive invocations var nodesToReplace = CollectInvocationsWalker.CollectInvocations(_context, _methodInfo, targetMethods); if (nodesToReplace.ContainsCriticalFailure) { _context.Log(_methodInfo.MethodSyntax.GetLocation(), $"An unsupported code was found for '{_methodInfo.MethodSymbol.Name}'. Abort processing."); return(null); } _context.Log(_methodInfo.MethodSyntax.GetLocation(), $"'{_methodInfo.MethodSymbol.Name}':" + $" {nodesToReplace.VoidCalls.Count} void call(s)" + $" {nodesToReplace.Assignments.Count} assignment(s)" + $", {nodesToReplace.DeclarationAndAssignments.Count} var declaration(s)" + $", {nodesToReplace.ReturnsRecursive.Count} recursive call(s) in return(s)" + $", {nodesToReplace.Returns.Count} return(s)"); // process all supported kinds of recursive invocations var allNodesToReplace = nodesToReplace.Returns.Cast <StatementSyntax>() .Concat(nodesToReplace.ReturnsRecursive) .Concat(nodesToReplace.VoidCalls.Select(t => t.containingStatement)) .Concat(nodesToReplace.Assignments.Select((t) => t.containingStatement)) .Concat(nodesToReplace.DeclarationAndAssignments.Select(t => t.containingStatement)); var newRoot = _methodInfo.MethodSyntax.Body.ReplaceNodes(allNodesToReplace, (origNode, curNode) => { // _context.Log("!! " + origNode.Kind() + " " + origNode.ToFullStringTrimmed()); switch (origNode.Kind()) { case SyntaxKind.ReturnStatement: return(ReplaceReturn(targetMethods, (ReturnStatementSyntax)origNode, (ReturnStatementSyntax)curNode)); case SyntaxKind.ExpressionStatement: var origExpressionNode = (ExpressionStatementSyntax)origNode; var expression = origExpressionNode.Expression; switch (expression.Kind()) { case SyntaxKind.InvocationExpression: return(ReplaceVoidCall(targetMethods, origExpressionNode, (ExpressionStatementSyntax)curNode)); case SyntaxKind.SimpleAssignmentExpression: return(ReplaceAssignment(targetMethods, origExpressionNode, (ExpressionStatementSyntax)curNode)); default: throw new AntiSOGenException($"Unexpected expression kind {expression.Kind()} to replace {origNode.ToFullStringTrimmed()}"); } case SyntaxKind.LocalDeclarationStatement: return(ReplaceLocalVarDeclrAssignment(targetMethods, (LocalDeclarationStatementSyntax)origNode, (LocalDeclarationStatementSyntax)curNode)); default: throw new AntiSOGenException($"Unexpected statement kind {origNode.Kind()} to replace {origNode.ToFullStringTrimmed()}"); } }); code.AddHeaderLine("\t\t// method body"); code.AddHeader(newRoot.ToFullString()); return(code.BuildString()); }
/// <summary> /// Create fsharp source-code representation of a <see cref="EnumDefinition"/>. /// </summary> /// <exception cref="Exceptions.InvalidNamespaceException"> /// Thrown when a invalid namespace identifier is given. /// </exception> /// <exception cref="Exceptions.OutOfBoundsValueException"> /// Thrown when enum value does not fit in given storage-type. /// </exception> /// <param name="enumDefinition">Enum to generate fsharp source-code for</param> /// <param name="namespace">Namespace to add the enum to</param> /// <param name="headerMode">Mode to use when adding a header</param> /// <param name="indentSize">How many spaces should be used for indents</param> /// <param name="newlineMode">Mode to use for ending lines</param> /// <param name="storageType">Underlying enum storage-type to use</param> /// <returns>String containing the genenerated fsharp sourcecode</returns> public static string ExportFSharp( this EnumDefinition enumDefinition, string @namespace, HeaderMode headerMode = HeaderMode.Default, int indentSize = 4, CodeBuilder.NewlineMode newlineMode = CodeBuilder.NewlineMode.Unix, StorageType storageType = StorageType.Implicit) { if (enumDefinition == null) { throw new ArgumentNullException(nameof(enumDefinition)); } if (!IdentifierValidator.ValidateNamespace(@namespace)) { throw new InvalidNamespaceException(@namespace); } foreach (var oobEntry in enumDefinition.Entries.Where(e => !storageType.Validate(e.Value))) { throw new OutOfBoundsValueException(storageType, oobEntry.Value); } var builder = new CodeBuilder(CodeBuilder.IndentMode.Spaces, indentSize, newlineMode); if (headerMode != HeaderMode.None) { builder.AddHeader(); builder.WriteEndLine(); } // Add namespace. builder.WriteLine($"namespace {@namespace}"); builder.WriteEndLine(); // Open System.CodeDom.Compiler (for the 'GeneratedCode' attribute) builder.WriteLine("open System.CodeDom.Compiler"); builder.WriteEndLine(); // Add type comment. if (!string.IsNullOrEmpty(enumDefinition.Comment)) { builder.AddSummary(enumDefinition.Comment); } // Add enum definition. var assemblyName = typeof(FSharpExporter).Assembly.GetName(); builder.WriteLine($"[<GeneratedCode(\"{assemblyName.Name}\", \"{assemblyName.Version}\")>]"); builder.WriteLine($"type {enumDefinition.Identifier} ="); // Add entries. foreach (var entry in enumDefinition.Entries) { var literalSuffix = storageType == StorageType.Implicit ? string.Empty : storageType.GetFSharpLiteralSuffix(); builder.WriteLine($"| {entry.Name} = {entry.Value}{literalSuffix}", additionalIndent: 1); } return(builder.Build()); }