public static void WriteConstructorsHelper(IEnumerable <INamedTypeSymbol> allTypes) { foreach (var t in allTypes.Select(o => o.ContainingNamespace.FullNameWithDot() + WriteType.TypeName(o))) { AllTypes.Add(t); } if (StaticConstructors.Count == 0) { return; //no need for it. } using (var writer = new ScalaWriter("CsRoot", "Constructors")) { writer.WriteLine(@"package CsRoot; /* This file lists all the static constructors. Scala doesn't have the same concept of static constructors as C#, so CsScala generated cctor() methods. You must call these manually. If you call Constructors.init(), all static constructors will be called at once and you won't have to worry about calling each one manually. */"); //foreach (var type in AllTypes.OrderBy(o => o)) // writer.WriteLine("import " + type + ";"); writer.WriteLine("object Constructors"); writer.WriteOpenBrace(); writer.WriteLine("def init()"); writer.WriteOpenBrace(); foreach (var cctor in StaticConstructors.OrderBy(o => o)) { writer.WriteLine(cctor + ".cctor();"); } writer.WriteCloseBrace(); writer.WriteCloseBrace(); } }
public static void Go(ScalaWriter writer, IEnumerable <EnumMemberDeclarationSyntax> allChildren) { writer.Write("object "); writer.Write(TypeState.Instance.TypeName); writer.Write("\r\n"); writer.WriteOpenBrace(); int lastEnumValue = -1; var values = allChildren.Select(o => new { Syntax = o, Value = DetermineEnumValue(o, ref lastEnumValue) }).ToList(); foreach (var value in values) { writer.WriteLine("final val " + WriteIdentifierName.TransformIdentifier(value.Syntax.Identifier.ValueText) + ":Int = " + value.Value + ";"); } writer.WriteLine(); writer.WriteLine(@"def ToString(n:java.lang.Integer):String = if (n == null) """" else ToString(n.intValue());"); writer.WriteLine("def ToString(e:Int):String ="); writer.WriteOpenBrace(); writer.WriteLine("return e match"); writer.WriteOpenBrace(); foreach (var value in values) { writer.WriteLine("case " + value.Value + " => \"" + value.Syntax.Identifier.ValueText + "\";"); } writer.WriteLine("case u => u.toString;"); writer.WriteCloseBrace(); writer.WriteCloseBrace(); writer.WriteLine(); writer.WriteLine("def Parse(s:String):Int ="); writer.WriteOpenBrace(); writer.WriteLine("return s match"); writer.WriteOpenBrace(); foreach (var value in values) { writer.WriteLine("case \"" + value.Syntax.Identifier.ValueText + "\" => " + value.Value + ";"); } writer.WriteLine("case u => u.toInt;"); writer.WriteCloseBrace(); writer.WriteCloseBrace(); writer.WriteLine(); writer.WriteIndent(); writer.Write("final val Values:Array[Int] = Array("); writer.Write(string.Join(", ", values.Select(o => o.Value.ToString()))); writer.Write(");\r\n"); writer.WriteCloseBrace(); }
public void WriteLoopOpening(ScalaWriter writer) { if (HasContinue) { writer.WriteLine("CsScala.cscontinue.breakable"); writer.WriteOpenBrace(); } }
public void WritePreLoop(ScalaWriter writer) { if (HasBreak) { writer.WriteLine("CsScala.csbreak.breakable"); writer.WriteOpenBrace(); } }
public static void Go(ScalaWriter writer, TryStatementSyntax tryStatement) { writer.WriteLine("try"); Core.Write(writer, tryStatement.Block); var catches = tryStatement.Catches.Where(o => Program.DoNotWrite.ContainsKey(o) == false).ToList(); if (catches.Count > 0) { writer.WriteLine("catch"); writer.WriteOpenBrace(); foreach (var catchClause in catches) { writer.WriteIndent(); //In C#, the base exception type is Exception, but on the JVM it is Throwable. Normally, JVM programs should not catch throwable, so we map the C# Exception type to the JVM Exception type by default. We attempted to change Exception to map to Throwable but ran into issues with things getting caught that shouldn't, such as Scala's "BreakControl" that's used on break statements. //if C# code really wants to catch all throwables, catch Exception and name the variable "allThrowables". This is a signal to CSScala that all throwables should be caught. However, use it with care, as it can cause complications. if (catchClause.Declaration == null) { writer.Write("case __ex: java.lang.Exception => "); } else { writer.Write("case "); writer.Write(string.IsNullOrWhiteSpace(catchClause.Declaration.Identifier.ValueText) ? "__ex" : WriteIdentifierName.TransformIdentifier(catchClause.Declaration.Identifier.ValueText)); writer.Write(": "); if (catchClause.Declaration.Identifier.ValueText == "allThrowables") { writer.Write("java.lang.Throwable"); } else { writer.Write(TypeProcessor.ConvertType(catchClause.Declaration.Type)); } writer.Write(" =>\r\n"); } writer.Indent++; foreach (var statement in catchClause.Block.Statements) { Core.Write(writer, statement); } writer.Indent--; } writer.WriteCloseBrace(); } if (tryStatement.Finally != null) { writer.WriteLine("finally"); Core.Write(writer, tryStatement.Finally.Block); } }
public static void WriteAnonymousType(AnonymousObjectCreationExpressionSyntax syntax) { var type = Program.GetModel(syntax).GetTypeInfo(syntax).Type.As <INamedTypeSymbol>(); var anonName = TypeName(type); using (var writer = new ScalaWriter("anonymoustypes", StripGeneric(anonName))) { var fields = type.GetMembers().OfType <IPropertySymbol>().OrderBy(o => o.Name).ToList(); writer.WriteLine("package anonymoustypes;"); WriteImports.Go(writer); writer.WriteIndent(); writer.Write("class "); writer.Write(anonName); writer.Write("("); bool first = true; foreach (var field in fields) { if (first) { first = false; } else { writer.Write(", "); } writer.Write("_"); writer.Write(WriteIdentifierName.TransformIdentifier(field.Name)); writer.Write(TypeProcessor.ConvertTypeWithColon(field.Type)); } writer.Write(")\r\n"); writer.WriteOpenBrace(); foreach (var field in fields) { writer.WriteIndent(); writer.Write("final var "); writer.Write(WriteIdentifierName.TransformIdentifier(field.Name)); writer.Write(TypeProcessor.ConvertTypeWithColon(field.Type)); writer.Write(" = _"); writer.Write(WriteIdentifierName.TransformIdentifier(field.Name)); writer.Write(";\r\n"); } writer.WriteCloseBrace(); } }
//public static void WriteInstanceConstructor(ScalaWriter writer, ConstructorDeclarationSyntax ctor) //{ // foreach (var field in TypeState.Instance.AllMembers // .OfType<BaseFieldDeclarationSyntax>() // .Where(o => !o.Modifiers.Any(SyntaxKind.StaticKeyword)) // .SelectMany(o => o.Declaration.Variables) // .Where(o => // (o.Initializer != null && !WriteField.IsConst(o.Parent.Parent.As<BaseFieldDeclarationSyntax>().Modifiers, o.Initializer, o.Parent.As<VariableDeclarationSyntax>().Type)) // || // (o.Initializer == null && TypeProcessor.ValueToReference(o.Parent.As<VariableDeclarationSyntax>().Type)) // || // o.Parent.Parent is EventFieldDeclarationSyntax)) // { // writer.WriteIndent(); // writer.Write(field.Identifier.ValueText); // writer.Write(" = "); // if (field.Initializer == null) // { // //The only way to get here with a null initializer is for a TypeProcess.ValueToReference field. // writer.Write("new "); // writer.Write(TypeProcessor.ConvertType(field.Parent.As<VariableDeclarationSyntax>().Type)); // writer.Write("()"); // } // else // { // Core.Write(writer, field.Initializer.Value); // } // writer.Write(";\r\n"); // } //} public static void WriteStaticConstructor(ScalaWriter writer, ConstructorDeclarationSyntax staticConstructor) { //var staticFieldsNeedingInitialization = TypeState.Instance.AllMembers // .OfType<BaseFieldDeclarationSyntax>() // .Where(o => o.Modifiers.Any(SyntaxKind.StaticKeyword)) // .SelectMany(o => o.Declaration.Variables) // .Where(o => // (o.Initializer != null && !WriteField.IsConst(o.Parent.Parent.As<BaseFieldDeclarationSyntax>().Modifiers, o.Initializer, o.Parent.As<VariableDeclarationSyntax>().Type)) // || // (o.Initializer == null && TypeProcessor.ValueToReference(o.Parent.As<VariableDeclarationSyntax>().Type)) // || // o.Parent.Parent is EventFieldDeclarationSyntax) // .ToList(); if (staticConstructor.Body == null) { return; } writer.WriteLine("def cctor()"); writer.WriteOpenBrace(); //foreach (var field in staticFieldsNeedingInitialization) //{ // writer.WriteIndent(); // writer.Write(field.Identifier.ValueText); // writer.Write(" = "); // if (field.Initializer == null) // { // //The only way to get here without an initializer is if it's a TypeProcessor.ValueToReference. // writer.Write("new "); // writer.Write(TypeProcessor.ConvertType(field.Parent.As<VariableDeclarationSyntax>().Type)); // writer.Write("()"); // } // else // { // Core.Write(writer, field.Initializer.As<EqualsValueClauseSyntax>().Value); // } // writer.Write(";\r\n"); //} foreach (var statement in staticConstructor.Body.As <BlockSyntax>().Statements) { Core.Write(writer, statement); } writer.WriteCloseBrace(); StaticConstructors.Add(TypeState.Instance.Partials.First().Symbol.ContainingNamespace.FullNameWithDot() + TypeState.Instance.TypeName); }
private static void WriteGetEnumeratorFunction(ScalaWriter writer, MethodDeclarationSyntax method, IMethodSymbol methodSymbol) { var returnType = TypeProcessor.ConvertType(methodSymbol.ReturnType); if (!returnType.StartsWith("System.Collections.Generic.IEnumerator[")) { return; //we only support the generic IEnumerator form of GetEnumerator. Anything else, just don't write out the method. } var enumerableType = returnType.RemoveFromStartOfString("System.Collections.Generic.IEnumerator[").RemoveFromEndOfString("]"); //We only support very simple GetEnumerator functions that pass on their call to some other collection. The body should be like "return <expr>.GetEnumerator();", otherwise don't write out the function at all. if (method.Body == null) { return; } if (method.Body.Statements.Count > 1) { return; } var returnStatement = method.Body.Statements.Single() as ReturnStatementSyntax; if (returnStatement == null) { return; } var invocation = returnStatement.Expression as InvocationExpressionSyntax; if (invocation == null) { return; } var member = invocation.Expression as MemberAccessExpressionSyntax; if (member == null) { return; } writer.WriteIndent(); writer.Write("def foreach[U](fn: "); writer.Write(enumerableType); writer.Write(" => U)\r\n"); writer.WriteOpenBrace(); writer.WriteIndent(); Core.Write(writer, member.Expression); writer.Write(".foreach(fn);\r\n"); writer.WriteCloseBrace(); }
public static void Go(ScalaWriter writer, LockStatementSyntax statement) { if (statement.DescendantNodes().OfType <ReturnStatementSyntax>().Any()) { throw new Exception("Cannot return from within a lock statement " + Utility.Descriptor(statement)); } writer.WriteIndent(); writer.Write("CsLock.Lock("); Core.Write(writer, statement.Expression); writer.Write(", () =>\r\n"); writer.WriteOpenBrace(); Core.WriteStatementAsBlock(writer, statement.Statement, false); writer.Indent--; writer.WriteIndent(); writer.Write("});\r\n"); }
public static void Go(ScalaWriter writer, WhileStatementSyntax whileStatement) { var info = new LoopInfo(whileStatement); info.WritePreLoop(writer); writer.WriteIndent(); writer.Write("while ("); Core.Write(writer, whileStatement.Condition); writer.Write(")\r\n"); writer.WriteOpenBrace(); info.WriteLoopOpening(writer); Core.WriteStatementAsBlock(writer, whileStatement.Statement, false); info.WriteLoopClosing(writer); writer.WriteCloseBrace(); info.WritePostLoop(writer); }
public static void WriteBlock(ScalaWriter writer, BlockSyntax block, bool writeBraces = true) { if (writeBraces) { writer.WriteOpenBrace(); } foreach (var statement in block.Statements) { Write(writer, statement); } TriviaProcessor.ProcessTrivias(writer, block.DescendantTrivia()); if (writeBraces) { writer.WriteCloseBrace(); } }
public static void Go(ScalaWriter writer, UsingStatementSyntax usingStatement) { var expression = usingStatement.Expression; //Ensure the using statement is a local variable - we can't deal with things we can't reliably repeat in the finally block var resource = Utility.TryGetIdentifier(expression); if (resource == null) { throw new Exception("Using statements must reference a local variable. " + Utility.Descriptor(usingStatement)); } writer.WriteLine("try"); Core.WriteStatementAsBlock(writer, usingStatement.Statement); writer.WriteLine("finally"); writer.WriteOpenBrace(); writer.WriteLine(resource + ".Dispose();"); writer.WriteCloseBrace(); }
public static void Go(ScalaWriter writer, ConversionOperatorDeclarationSyntax method) { if (method.ImplicitOrExplicitKeyword.Kind() != SyntaxKind.ExplicitKeyword) { throw new Exception("Implicit cast operators are not supported " + Utility.Descriptor(method)); } writer.WriteIndent(); writer.Write("def op_Explicit_"); writer.Write(TypeProcessor.ConvertType(method.Type)); writer.Write("("); bool firstParam = true; foreach (var param in method.ParameterList.Parameters) { if (firstParam) { firstParam = false; } else { writer.Write(", "); } writer.Write(WriteIdentifierName.TransformIdentifier(param.Identifier.ValueText)); writer.Write(TypeProcessor.ConvertTypeWithColon(param.Type)); } writer.Write(")"); writer.Write(TypeProcessor.ConvertTypeWithColon(method.Type)); writer.Write(" =\r\n"); writer.WriteOpenBrace(); foreach (var statement in method.Body.Statements) { Core.Write(writer, statement); } writer.WriteCloseBrace(); }
public static void WriteStatementAsBlock(ScalaWriter writer, StatementSyntax statement, bool writeBraces = true) { if (statement is BlockSyntax) { WriteBlock(writer, statement.As <BlockSyntax>(), writeBraces); } else { if (writeBraces) { writer.WriteOpenBrace(); } Core.Write(writer, statement); TriviaProcessor.ProcessTrivias(writer, statement.DescendantTrivia()); if (writeBraces) { writer.WriteCloseBrace(); } } }
public static void Go(ScalaWriter writer, PropertyDeclarationSyntax property) { Action <AccessorDeclarationSyntax, bool> writeRegion = (region, get) => { writer.WriteIndent(); if (property.Modifiers.Any(SyntaxKind.OverrideKeyword)) { writer.Write("override "); } if (property.Modifiers.Any(SyntaxKind.PrivateKeyword)) { writer.Write("private "); } writer.Write("def "); writer.Write(WriteIdentifierName.TransformIdentifier(property.Identifier.ValueText)); if (get) { writer.Write(TypeProcessor.ConvertTypeWithColon(property.Type)); } else { writer.Write("_=(value"); writer.Write(TypeProcessor.ConvertTypeWithColon(property.Type)); writer.Write(")"); } if (property.Modifiers.Any(SyntaxKind.AbstractKeyword) || region.Body == null) { writer.Write(";\r\n"); } else { writer.Write(" =\r\n"); Core.WriteBlock(writer, region.Body.As <BlockSyntax>()); } }; var getter = property.AccessorList.Accessors.SingleOrDefault(o => o.Keyword.Kind() == SyntaxKind.GetKeyword); var setter = property.AccessorList.Accessors.SingleOrDefault(o => o.Keyword.Kind() == SyntaxKind.SetKeyword); if (getter == null && setter == null) { throw new Exception("Property must have either a get or a set"); } if (getter != null && setter != null && setter.Body == null && getter.Body == null) { //Both get and set are null, which means this is an automatic property. For our purposes, this is the equivilant of a field WriteField.Go(writer, property.Modifiers, WriteIdentifierName.TransformIdentifier(property.Identifier.ValueText), property.Type); } else { if (getter != null) { writeRegion(getter, true); } else if (setter != null) { //Scala does not allow having a setter without a getter. Write out a getter. writer.Write("def "); writer.Write(WriteIdentifierName.TransformIdentifier(property.Identifier.ValueText)); writer.Write(TypeProcessor.ConvertTypeWithColon(property.Type)); writer.Write(" =\r\n"); writer.WriteOpenBrace(); writer.WriteLine("throw new Exception(\"No getter defined\");"); writer.WriteCloseBrace(); } if (setter != null) { writeRegion(setter, false); } } }
private static void Go(ScalaWriter writer, IEnumerable <ParameterSyntax> parameters, SyntaxNode body, TypeInfo type) { var methodSymbol = type.ConvertedType.As <INamedTypeSymbol>().DelegateInvokeMethod.As <IMethodSymbol>(); writer.Write("("); for (int pi = 0; pi < parameters.Count(); pi++) { var parameter = parameters.ElementAt(pi); if (pi > 0) { writer.Write(", "); } writer.Write(WriteIdentifierName.TransformIdentifier(parameter.Identifier.ValueText)); if (parameter.Type != null) { writer.Write(TypeProcessor.ConvertTypeWithColon(parameter.Type)); } else { writer.Write(TypeProcessor.ConvertTypeWithColon(methodSymbol.Parameters[pi].Type)); } } writer.Write(") => "); bool returnsVoid = methodSymbol.ReturnType.ToString() == "void"; if (body is BlockSyntax) { writer.Write("\r\n"); writer.WriteOpenBrace(); var statements = body.As <BlockSyntax>().Statements; var lastStatement = statements.LastOrDefault() as ReturnStatementSyntax; var returnStatements = FindReturnStatements(body); if (returnStatements.Count > 0 && (lastStatement == null || returnStatements.Except(lastStatement).Any())) { //Lambda has branching returns. We must use a breakable block since scala can't return from a lambda like C# can TypeState.Instance.InLambdaBreakable++; writer.WriteLine("val __lambdabreak = new Breaks;"); if (!returnsVoid) { writer.WriteIndent(); writer.Write("var __lambdareturn:"); writer.Write(TypeProcessor.ConvertType(methodSymbol.ReturnType)); writer.Write(" = "); writer.Write(TypeProcessor.DefaultValue(methodSymbol.ReturnType)); writer.Write(";\r\n"); } writer.WriteLine("__lambdabreak.breakable"); writer.WriteOpenBrace(); foreach (var statement in statements) { if (statement == lastStatement && !returnsVoid) { //Manually write it so we avoid the final break that WriteReturnStatement does writer.WriteIndent(); writer.Write("__lambdareturn = "); Core.Write(writer, lastStatement.Expression); writer.Write(";\r\n"); } else { Core.Write(writer, statement); } } TriviaProcessor.ProcessTrivias(writer, body.DescendantTrivia()); writer.WriteCloseBrace(); if (!returnsVoid) { writer.WriteLine("__lambdareturn;"); } TypeState.Instance.InLambdaBreakable--; } else { foreach (var statement in statements) { if (statement == lastStatement) { writer.WriteIndent(); Core.Write(writer, lastStatement.Expression); writer.Write(";\r\n"); } else { Core.Write(writer, statement); } } } writer.Indent--; writer.WriteIndent(); writer.Write("}"); } else { writer.Write(" { "); Core.Write(writer, body); writer.Write("; }"); } if (!returnsVoid) { writer.Write(TypeProcessor.ConvertTypeWithColon(methodSymbol.ReturnType)); } }
public static void Go(ScalaWriter writer, ForStatementSyntax forStatement) { var info = new LoopInfo(forStatement); writer.WriteLine("{ //for"); writer.Indent++; info.WritePreLoop(writer); if (forStatement.Declaration != null) { foreach (var variable in forStatement.Declaration.Variables) { writer.WriteIndent(); writer.Write("var "); writer.Write(WriteIdentifierName.TransformIdentifier(variable.Identifier.ValueText)); writer.Write(TypeProcessor.ConvertTypeWithColon(forStatement.Declaration.Type)); if (variable.Initializer != null) { writer.Write(" = "); Core.Write(writer, variable.Initializer.Value); } writer.Write(";\r\n"); } } foreach (var init in forStatement.Initializers) { writer.WriteIndent(); Core.Write(writer, init); writer.Write(";\r\n"); } writer.WriteIndent(); writer.Write("while ("); if (forStatement.Condition == null) { writer.Write("true"); } else { Core.Write(writer, forStatement.Condition); } writer.Write(")\r\n"); writer.WriteOpenBrace(); info.WriteLoopOpening(writer); Core.WriteStatementAsBlock(writer, forStatement.Statement, false); info.WriteLoopClosing(writer); foreach (var iterator in forStatement.Incrementors) { writer.WriteIndent(); Core.Write(writer, iterator); writer.Write(";\r\n"); } writer.WriteCloseBrace(); info.WritePostLoop(writer); writer.Indent--; writer.WriteLine("} //end for"); }
public static void Go(ScalaWriter writer, ForEachStatementSyntax foreachStatement) { var info = new LoopInfo(foreachStatement); var types = Program.GetModel(foreachStatement).GetTypeInfo(foreachStatement.Expression); var typeStr = TypeProcessor.GenericTypeName(types.Type); if (types.Type is IArrayTypeSymbol) { //It's faster to "while" through arrays than "for" through them writer.WriteOpenBrace(); info.WritePreLoop(writer); writer.WriteLine("var __foreachindex:Int = 0;"); writer.WriteIndent(); writer.Write("val __foreacharray = "); Core.Write(writer, foreachStatement.Expression); writer.Write(";\r\n"); writer.WriteLine("while (__foreachindex < __foreacharray.length)"); writer.WriteOpenBrace(); writer.WriteIndent(); writer.Write("val "); writer.Write(WriteIdentifierName.TransformIdentifier(foreachStatement.Identifier.ValueText)); writer.Write(" = __foreacharray(__foreachindex);\r\n"); info.WriteLoopOpening(writer); Core.WriteStatementAsBlock(writer, foreachStatement.Statement, false); info.WriteLoopClosing(writer); writer.WriteLine("__foreachindex += 1;"); writer.WriteCloseBrace(); info.WritePostLoop(writer); writer.WriteCloseBrace(); } else if (typeStr == "System.Collections.Generic.List<>" //|| typeStr == "System.Collections.Generic.Dictionary<,>" || typeStr == "System.Collections.Generic.Dictionary<,>.KeyCollection" || typeStr == "System.Collections.Generic.Dictionary<,>.ValueCollection") { //It's faster to "while" over a list's iterator than to "for" through it writer.WriteOpenBrace(); info.WritePreLoop(writer); writer.WriteIndent(); writer.Write("val __foreachiterator = "); Core.Write(writer, foreachStatement.Expression); writer.Write(".iterator();\r\n"); writer.WriteLine("while (__foreachiterator.hasNext())"); writer.WriteOpenBrace(); writer.WriteIndent(); writer.Write("val "); writer.Write(WriteIdentifierName.TransformIdentifier(foreachStatement.Identifier.ValueText)); writer.Write(" = __foreachiterator.next();\r\n"); info.WriteLoopOpening(writer); Core.WriteStatementAsBlock(writer, foreachStatement.Statement, false); info.WriteLoopClosing(writer); writer.WriteCloseBrace(); info.WritePostLoop(writer); writer.WriteCloseBrace(); } else { info.WritePreLoop(writer); writer.WriteIndent(); writer.Write("for ("); writer.Write(WriteIdentifierName.TransformIdentifier(foreachStatement.Identifier.ValueText)); writer.Write(" <- "); Core.Write(writer, foreachStatement.Expression); writer.Write(")\r\n"); writer.WriteOpenBrace(); info.WriteLoopOpening(writer); Core.WriteStatementAsBlock(writer, foreachStatement.Statement, false); info.WriteLoopClosing(writer); writer.WriteCloseBrace(); info.WritePostLoop(writer); } }
public static void Go(ScalaWriter writer, MethodDeclarationSyntax method) { if (method.Modifiers.Any(SyntaxKind.PartialKeyword) && method.Body == null) { //We only want to render out one of the two partial methods. If there's another, skip this one. if (TypeState.Instance.Partials.SelectMany(o => o.Syntax.As <ClassDeclarationSyntax>().Members) .OfType <MethodDeclarationSyntax>() .Except(method) .Where(o => o.Identifier.ValueText == method.Identifier.ValueText) .Any()) { return; } } var methodSymbol = Program.GetModel(method).GetDeclaredSymbol(method); if (method.Identifier.ValueText == "GetEnumerator") { WriteGetEnumeratorFunction(writer, method, methodSymbol); return; } writer.WriteIndent(); if (ShouldUseOverrideKeyword(method, methodSymbol)) { writer.Write("override "); } if (method.Modifiers.Any(SyntaxKind.PrivateKeyword)) { writer.Write("private "); } writer.Write("def "); var methodName = OverloadResolver.MethodName(methodSymbol); if (methodName == "ToString") { methodName = "toString"; } else if (methodName == "Equals") { methodName = "equals"; } else if (methodName == "GetHashCode") { methodName = "hashCode"; } else if (methodName == "Main") { methodName = "main"; } writer.Write(methodName); if (method.TypeParameterList != null) { writer.Write("["); writer.Write(string.Join(", ", method.TypeParameterList.Parameters.Select(o => TypeParameter(o, methodSymbol, method)))); writer.Write("]"); } writer.Write("("); var firstParam = true; foreach (var parameter in method.ParameterList.Parameters) { bool isRef = parameter.Modifiers.Any(SyntaxKind.OutKeyword) || parameter.Modifiers.Any(SyntaxKind.RefKeyword); if (firstParam) { firstParam = false; } else { writer.Write(", "); } writer.Write(WriteIdentifierName.TransformIdentifier(parameter.Identifier.ValueText)); if (isRef) { writer.Write(":CsRef["); writer.Write(TypeProcessor.ConvertType(parameter.Type)); writer.Write("]"); Program.RefOutSymbols.TryAdd(Program.GetModel(method).GetDeclaredSymbol(parameter), null); } else { writer.Write(TypeProcessor.ConvertTypeWithColon(parameter.Type)); } if (parameter.Default != null) { writer.Write(" = "); Core.Write(writer, parameter.Default.Value); } } writer.Write(")"); bool returnsVoid = method.ReturnType.ToString() == "void"; if (!returnsVoid) { writer.Write(TypeProcessor.ConvertTypeWithColon(method.ReturnType)); } if (method.Modifiers.Any(SyntaxKind.AbstractKeyword) || method.Parent is InterfaceDeclarationSyntax) { writer.Write(";\r\n"); } else { if (!returnsVoid) { writer.Write(" ="); } writer.Write("\r\n"); writer.WriteOpenBrace(); if (method.Body != null) { foreach (var statement in method.Body.Statements) { Core.Write(writer, statement); } TriviaProcessor.ProcessTrivias(writer, method.Body.DescendantTrivia()); } writer.WriteCloseBrace(); } }
public static void Go(ScalaWriter writer, SwitchStatementSyntax switchStatement) { writer.WriteIndent(); Core.Write(writer, switchStatement.Expression); writer.Write(" match\r\n"); writer.WriteOpenBrace(); //First process all blocks except the section with the default block foreach (var section in switchStatement.Sections.Where(o => o.Labels.None(z => z.Keyword.Kind() == SyntaxKind.DefaultKeyword))) { writer.WriteIndent(); writer.Write("case "); var firstLabel = true; foreach (var label in section.Labels) { if (firstLabel) { firstLabel = false; } else { writer.Write(" | "); } Core.Write(writer, label.ChildNodes().Single(), true); } writer.Write(" =>\r\n"); writer.Indent++; foreach (var statement in section.Statements) { if (!(statement is BreakStatementSyntax)) { Core.Write(writer, statement); } } writer.Indent--; } //Now write the default section var defaultSection = switchStatement.Sections.SingleOrDefault(o => o.Labels.Any(z => z.Keyword.Kind() == SyntaxKind.DefaultKeyword)); if (defaultSection != null) { if (defaultSection.Labels.Count > 1) { throw new Exception("Cannot fall-through into or out of the default section of switch statement " + Utility.Descriptor(defaultSection)); } writer.WriteLine("case _ =>"); writer.Indent++; foreach (var statement in defaultSection.Statements) { if (!(statement is BreakStatementSyntax)) { Core.Write(writer, statement); } } writer.Indent--; } else { //Scala will throw a MatchError if nothing matches, whereas C# just skips switch statements with no match. Therefore, if no default section is provided, just write out a do-nothing default so that MatchError is not thrown writer.WriteLine("case _ =>"); } writer.WriteCloseBrace(); }
public static void Go() { var partials = TypeState.Instance.Partials; var first = partials.First(); using (var writer = new ScalaWriter(first.Symbol.ContainingNamespace.FullName(), TypeState.Instance.TypeName)) { var bases = partials .Select(o => o.Syntax.BaseList) .Where(o => o != null) .SelectMany(o => o.Types) .Select(o => Program.GetModel(o).GetTypeInfo(o.Type).ConvertedType) .Distinct() .ToList(); var interfaces = bases.Where(o => o.TypeKind == TypeKind.Interface).ToList(); //TypeState.Instance.DerivesFromObject = bases.Count == interfaces.Count; var package = first.Symbol.ContainingNamespace.FullName(); if (package.Length > 0) { writer.WriteLine("package " + package + @";"); } WriteImports.Go(writer); if (first.Syntax is EnumDeclarationSyntax) { WriteEnum.Go(writer, TypeState.Instance.Partials.Select(o => o.Syntax).Cast <EnumDeclarationSyntax>().SelectMany(o => o.Members).Where(o => !Program.DoNotWrite.ContainsKey(o))); return; } TypeState.Instance.AllMembers = partials.Select(o => o.Syntax).Cast <TypeDeclarationSyntax>().SelectMany(o => o.Members).Where(o => !Program.DoNotWrite.ContainsKey(o)).ToList(); var allMembersToWrite = TypeState.Instance.AllMembers .Where(member => !(member is TypeDeclarationSyntax) && !(member is EnumDeclarationSyntax) && !(member is DelegateDeclarationSyntax)) .ToList(); var instanceCtors = TypeState.Instance.AllMembers.OfType <ConstructorDeclarationSyntax>() .Where(o => !o.Modifiers.Any(SyntaxKind.StaticKeyword)) .ToList(); if (instanceCtors.Count > 1) { throw new Exception("Overloaded constructors are not supported. Consider changing all but one to static Create methods " + Utility.Descriptor(first.Syntax)); } var ctorOpt = instanceCtors.SingleOrDefault(); foreach (var staticMembers in new[] { true, false }) { var membersToWrite = allMembersToWrite.Where(o => IsStatic(o) == staticMembers).ToList(); if (membersToWrite.Count == 0 && (staticMembers || partials.Any(o => o.Syntax.Modifiers.Any(SyntaxKind.StaticKeyword)))) { continue; } if (staticMembers) { writer.Write("object "); } else if (first.Syntax.Kind() == SyntaxKind.InterfaceDeclaration) { writer.Write("trait "); } else { if (partials.Any(o => o.Syntax.Modifiers.Any(SyntaxKind.AbstractKeyword))) { writer.Write("abstract "); } writer.Write("class "); } writer.Write(TypeState.Instance.TypeName); if (!staticMembers && first.Syntax is TypeDeclarationSyntax) { //Look for generic arguments var genericArgs = partials .Select(o => o.Syntax) .Cast <TypeDeclarationSyntax>() .Where(o => o.TypeParameterList != null) .SelectMany(o => o.TypeParameterList.Parameters) .ToList(); if (genericArgs.Count > 0) { writer.Write("["); writer.Write(string.Join(", ", genericArgs.Select(o => TypeParameter(o)))); writer.Write("]"); } //Write constructor arguments if (ctorOpt != null && ctorOpt.ParameterList.Parameters.Count > 0) { writer.Write("("); var firstParameter = true; foreach (var parameter in ctorOpt.ParameterList.Parameters) { if (firstParameter) { firstParameter = false; } else { writer.Write(", "); } writer.Write(WriteIdentifierName.TransformIdentifier(parameter.Identifier.ValueText)); writer.Write(TypeProcessor.ConvertTypeWithColon(parameter.Type)); if (parameter.Default != null) { writer.Write(" = "); Core.Write(writer, parameter.Default.Value); } } writer.Write(")"); } bool firstBase = true; foreach (var baseType in bases.OrderBy(o => o.TypeKind == TypeKind.Interface ? 1 : 0)) { if (firstBase) { writer.Write(" extends "); } else { writer.Write(" with "); } writer.Write(TypeProcessor.ConvertType(baseType)); if (firstBase && ctorOpt != null && ctorOpt.Initializer != null && ctorOpt.Initializer.ArgumentList.Arguments.Count > 0) { writer.Write("("); bool firstArg = true; foreach (var init in ctorOpt.Initializer.ArgumentList.Arguments) { if (firstArg) { firstArg = false; } else { writer.Write(", "); } Core.Write(writer, init.Expression); } writer.Write(")"); } firstBase = false; } } writer.Write("\r\n"); writer.WriteOpenBrace(); var fields = membersToWrite.OfType <FieldDeclarationSyntax>().ToList(); var nonFields = membersToWrite.Except(fields); fields = SortFields(fields); foreach (var member in fields) { Core.Write(writer, member); } foreach (var member in nonFields) { Core.Write(writer, member); } if (!staticMembers && ctorOpt != null && ctorOpt.Body != null && ctorOpt.Body.As <BlockSyntax>().Statements.Count > 0) { writer.WriteLine(); Core.WriteBlock(writer, ctorOpt.Body.As <BlockSyntax>(), true); //render braces so local ctor variables don't bleed out into fields } writer.WriteCloseBrace(); } } }