public static void Go(ScalaWriter writer, SyntaxTokenList modifiers, string name, TypeSyntax type, EqualsValueClauseSyntax initializerOpt = null) { writer.WriteIndent(); var isConst = IsConst(modifiers, initializerOpt, type); WriteFieldModifiers(writer, modifiers); if (isConst) { writer.Write("final val "); } else { writer.Write("var "); } writer.Write(name); writer.Write(TypeProcessor.ConvertTypeWithColon(type)); writer.Write(" = "); if (initializerOpt != null) { Core.Write(writer, initializerOpt.Value); } else { writer.Write(TypeProcessor.DefaultValue(type)); } writer.Write(";"); writer.WriteLine(); }
public static void Go(ScalaWriter writer, LocalDeclarationStatementSyntax declaration) { foreach (var variable in declaration.Declaration.Variables) { var symbol = Program.GetModel(declaration).GetDeclaredSymbol(variable); var isRef = UsedAsRef(variable, symbol); writer.WriteIndent(); writer.Write("var "); writer.Write(WriteIdentifierName.TransformIdentifier(variable.Identifier.ValueText)); if (isRef) { var typeStr = TypeProcessor.ConvertType(declaration.Declaration.Type); writer.Write(":CsRef["); writer.Write(typeStr); writer.Write("]"); Program.RefOutSymbols.TryAdd(symbol, null); writer.Write(" = new CsRef["); writer.Write(typeStr); writer.Write("]("); if (variable.Initializer == null) { writer.Write(TypeProcessor.DefaultValue(declaration.Declaration.Type)); } else { Core.Write(writer, variable.Initializer.As <EqualsValueClauseSyntax>().Value); } writer.Write(")"); } else { writer.Write(TypeProcessor.ConvertTypeWithColon(declaration.Declaration.Type)); writer.Write(" = "); if (variable.Initializer != null) { Core.Write(writer, variable.Initializer.As <EqualsValueClauseSyntax>().Value); } else { writer.Write(TypeProcessor.DefaultValue(declaration.Declaration.Type)); } } writer.Write(";\r\n"); } }
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 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 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); } } }
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() { 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(); } } }
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, MemberAccessExpressionSyntax expression) { var model = Program.GetModel(expression); var memberName = expression.Name.Identifier.ValueText; var type = model.GetTypeInfo(expression.Expression).ConvertedType; var typeStr = TypeProcessor.GenericTypeName(type); if (expression.Expression is PredefinedTypeSyntax) { if (memberName == "MaxValue" || memberName == "MinValue" || memberName == "NaN") { var predefined = expression.Expression.ToString(); if (predefined.StartsWith("u")) { //Scala does not have unsigned types. Forward these to CsScala writer.Write("System.CsScala."); writer.Write(predefined); writer.Write(memberName); } else { writer.Write(predefined[0].ToString().ToUpper()); writer.Write(predefined.Substring(1)); writer.Write("."); writer.Write(memberName); } } else { var field = System.Type.GetType(typeStr).GetField(memberName); if (field == null) { throw new Exception("Cannot use " + memberName + " as a field. If you're passing a function, wrap a closure around it. " + Utility.Descriptor(expression)); } var val = field.GetValue(null); if (val is string) { writer.Write("\"" + val + "\""); } else { writer.Write(val.ToString()); } } } else if (type.OriginalDefinition is INamedTypeSymbol && type.OriginalDefinition.As <INamedTypeSymbol>().SpecialType == SpecialType.System_Nullable_T) { switch (memberName) { case "HasValue": writer.Write("("); WriteMember(writer, expression.Expression); writer.Write(" != null)"); break; case "Value": var nullableType = TypeProcessor.ConvertType(type.As <INamedTypeSymbol>().TypeArguments.Single()); WriteMember(writer, expression.Expression); if (TypeProcessor.IsPrimitiveType(nullableType)) { writer.Write("."); writer.Write(nullableType[0].ToString().ToLower()); writer.Write(nullableType.Substring(1)); writer.Write("Value()"); } break; default: throw new Exception("Need handler for Nullable." + memberName + " " + Utility.Descriptor(expression)); } } else { var translate = PropertyTranslation.Get(typeStr, memberName); if (translate != null && translate.ExtensionMethod != null) { writer.Write(translate.ExtensionMethod); writer.Write("("); if (!(model.GetSymbolInfo(expression.Expression).Symbol is INamedTypeSymbol)) { Core.Write(writer, expression.Expression); } writer.Write(")"); return; } if (translate != null) { memberName = translate.ReplaceWith; } else { memberName = WriteIdentifierName.TransformIdentifier(memberName); } if (type != null) //if type is null, then we're just a namespace. We can ignore these. { WriteMember(writer, expression.Expression); writer.Write("."); } writer.Write(memberName); if (expression.Name is GenericNameSyntax) { var gen = expression.Name.As <GenericNameSyntax>(); writer.Write("["); bool first = true; foreach (var g in gen.TypeArgumentList.Arguments) { if (first) { first = false; } else { writer.Write(", "); } writer.Write(TypeProcessor.ConvertTypeWithColon(g)); } writer.Write("]"); } } }
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)); } }