[scripting] more parenthesis handling improvements

This commit is contained in:
Adriano Carlos Verona 2017-06-21 16:11:00 -03:00
Родитель b431bf2c21
Коммит 750ca6e853
7 изменённых файлов: 90 добавлений и 42 удалений

Просмотреть файл

@ -2,6 +2,13 @@ using System;
namespace UnityScript2CSharp.Tests
{
public class C
{
public static int staticField;
public static int staticMethod() { return 1; }
public int instanceMethod() { return 1; }
}
public struct Other
{
public string value;

Просмотреть файл

@ -65,6 +65,19 @@ namespace UnityScript2CSharp.Tests
AssertConversion(sources, expectedConverted);
}
[TestCase("o.staticField = 1;", "C.staticField = 1;")]
[TestCase("var i = o.staticField + 1;", "int i = C.staticField + 1;")]
[TestCase("var i = o.staticField + o.staticMethod();", "int i = C.staticField + C.staticMethod();")]
[TestCase("o.staticMethod();", "C.staticMethod();")]
[TestCase("C.staticMethod();", "C.staticMethod();")] // Proof that static references through a type ref are not affected
public void Static_Members_Through_Instance_Are_Updated(string usSnippet, string csSnippet)
{
SourceFile[] sources = { new SourceFile("static_member.js", $"import UnityScript2CSharp.Tests; function F(o:C) {{ {usSnippet} return 1; }}") };
SourceFile[] expectedConverted = { new SourceFile("static_member.cs", "using UnityScript2CSharp.Tests; " + DefaultGeneratedClass + $"static_member : MonoBehaviour {{ public virtual int F(C o) {{ {csSnippet} return 1; }} }}") };
AssertConversion(sources, expectedConverted);
}
[Test]
public void Additional_Imports()
{

Просмотреть файл

@ -1,4 +1,5 @@
using Boo.Lang.Compiler.Ast;
using System.Linq;
using Boo.Lang.Compiler.Ast;
using Boo.Lang.Compiler.TypeSystem;
namespace UnityScript2CSharp.Extensions
@ -10,7 +11,7 @@ namespace UnityScript2CSharp.Extensions
if (node.NodeType != NodeType.MethodInvocationExpression)
return false;
var invocation = (MethodInvocationExpression) node;
var invocation = (MethodInvocationExpression)node;
return invocation.Target.Entity != null && invocation.Target.Entity.EntityType == EntityType.Constructor;
}
@ -19,10 +20,15 @@ namespace UnityScript2CSharp.Extensions
if (node.NodeType != NodeType.GenericReferenceExpression)
return false;
var gre = (GenericReferenceExpression) node;
var gre = (GenericReferenceExpression)node;
// Arrays in UnityScript are represented as a GenericReferenceExpession
var target = gre.Target as ReferenceExpression;
return target != null && target.Name == "array";
}
public static bool NeedsQualificationFor(this Node node, INamespace ns)
{
return node.GetAncestors<Import>().Any(imp => imp.Namespace == ns.FullName);
}
}
}

Просмотреть файл

@ -0,0 +1,24 @@
using Boo.Lang.Compiler.Ast;
using Boo.Lang.Compiler.Steps;
using Boo.Lang.Compiler.TypeSystem;
using UnityScript2CSharp.Extensions;
namespace UnityScript2CSharp.Steps
{
class InstanceToTypeReferencedStaticMemberReference : AbstractTransformerCompilerStep
{
public override void OnMemberReferenceExpression(MemberReferenceExpression node)
{
IMember member = node.Entity as IMember;
if (member != null && member.IsStatic && node.Target.Entity.EntityType != EntityType.Type)
{
var declaringType = node.Target.ExpressionType;
var needsQualification = node.NeedsQualificationFor(declaringType.ParentNamespace);
node.Replace(node.Target, new ReferenceExpression(needsQualification ? declaringType.FullName : declaringType.Name));
}
base.OnMemberReferenceExpression(node);
}
}
}

Просмотреть файл

@ -113,6 +113,7 @@
<Compile Include="Steps\ApplyEnumToImplicitConversions.cs" />
<Compile Include="Steps\ExpandAssignmentToValueTypeMembers.cs" />
<Compile Include="Steps\InferredMethodReturnTypeFix.cs" />
<Compile Include="Steps\InstanceToTypeReferencedStaticMemberReference.cs" />
<Compile Include="Steps\PromoteImplicitBooleanConversionsToExplicitComparisons.cs" />
<Compile Include="Steps\InjectTypeOfExpressionsInArgumentsOfSystemType.cs" />
<Compile Include="Program.cs" />

Просмотреть файл

@ -135,6 +135,7 @@ namespace UnityScript2CSharp
adjustedPipeline.Add(new ReplaceGetSetItemMethodsWithOriginalIndexers());
adjustedPipeline.Add(new PromoteImplicitBooleanConversionsToExplicitComparisons());
adjustedPipeline.Add(new InstanceToTypeReferencedStaticMemberReference());
_compiler.Parameters.Pipeline = adjustedPipeline;
}

Просмотреть файл

@ -606,21 +606,21 @@ namespace UnityScript2CSharp
public override void OnBinaryExpression(BinaryExpression node)
{
WrapWith(NeedParensAround(node), "(", ")", delegate()
{
var isDeclarationStatement = node.Operator == BinaryOperatorType.Assign &&
node.Left.NodeType == NodeType.ReferenceExpression && node.IsSynthetic;
if (isDeclarationStatement)
{
var localDeclaration = (InternalLocal) node.Left.Entity;
localDeclaration.OriginalDeclaration.Type.Accept(this);
_writer.Write(" ");
}
var isDeclarationStatement = node.Operator == BinaryOperatorType.Assign &&
node.Left.NodeType == NodeType.ReferenceExpression && node.IsSynthetic;
node.Left.Accept(this);
_writer.Write($" {CSharpOperatorFor(node.Operator)} ");
node.Right.Accept(this);
});
if (isDeclarationStatement)
{
var localDeclaration = (InternalLocal)node.Left.Entity;
localDeclaration.OriginalDeclaration.Type.Accept(this);
_writer.Write(" ");
}
node.Left.Accept(this);
_writer.Write($" {CSharpOperatorFor(node.Operator)} ");
node.Right.Accept(this);
});
}
public override void OnConditionalExpression(ConditionalExpression node)
@ -629,13 +629,13 @@ namespace UnityScript2CSharp
var needsParens = parent != null && (parent.Right != node || parent.Operator != BinaryOperatorType.Assign);
WrapWith(needsParens , "(", ")", delegate
{
node.Condition.Accept(this);
_writer.Write(" ? ");
VisitWrapping(node.TrueValue, node.TrueValue.NodeType == NodeType.ConditionalExpression, "(", ")");
_writer.Write(" : ");
VisitWrapping(node.FalseValue, node.FalseValue.NodeType == NodeType.ConditionalExpression, "(", ")");
});
{
node.Condition.Accept(this);
_writer.Write(" ? ");
VisitWrapping(node.TrueValue, node.TrueValue.NodeType == NodeType.ConditionalExpression, "(", ")");
_writer.Write(" : ");
VisitWrapping(node.FalseValue, node.FalseValue.NodeType == NodeType.ConditionalExpression, "(", ")");
});
}
public override void OnReferenceExpression(ReferenceExpression node)
@ -843,7 +843,6 @@ namespace UnityScript2CSharp
public override void OnTryCastExpression(TryCastExpression node)
{
var mre = node.ParentNode as MemberReferenceExpression;
var isTargetOfMemberReferenceExpression = NeedParensAround(node);
VisitWrapping(node.Target, isTargetOfMemberReferenceExpression, "(");
@ -853,19 +852,13 @@ namespace UnityScript2CSharp
public override void OnCastExpression(CastExpression node)
{
var mre = node.ParentNode as TryCastExpression;
var isTargetOfExpression = mre != null && mre.Target == node;
if (isTargetOfExpression)
_writer.Write("(");
_writer.Write("(");
node.Type.Accept(this);
_writer.Write(") ");
node.Target.Accept(this);
if (isTargetOfExpression)
_writer.Write(")");
WrapWith(NeedParensAround(node), "(", ")", delegate
{
_writer.Write("(");
node.Type.Accept(this);
_writer.Write(") ");
node.Target.Accept(this);
});
}
public override void OnTypeofExpression(TypeofExpression node)
@ -1085,25 +1078,28 @@ namespace UnityScript2CSharp
switch (nodeParent.NodeType)
{
case NodeType.ExpressionStatement:
case NodeType.MacroStatement:
case NodeType.IfStatement:
case NodeType.WhileStatement:
case NodeType.UnlessStatement:
return ((ConditionalStatement)nodeParent).Condition != e;
case NodeType.ExpressionStatement:
case NodeType.MacroStatement:
return false;
case NodeType.MethodInvocationExpression:
return ((MethodInvocationExpression) nodeParent).Arguments.Any(a => a == e);
return !((MethodInvocationExpression)nodeParent).Arguments.Any(a => a == e);
case NodeType.BinaryExpression:
return ((BinaryExpression) nodeParent).Right != e;
return ((BinaryExpression)nodeParent).Right != e;
case NodeType.ReturnStatement:
return ((ReturnStatement) nodeParent).Expression != e;
return ((ReturnStatement)nodeParent).Expression != e;
case NodeType.ConditionalExpression:
return nodeParent.ParentNode.NodeType == NodeType.BinaryExpression && ((BinaryExpression)nodeParent.ParentNode).Operator != BinaryOperatorType.Assign;
}
return true;
}