[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 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 struct Other
{ {
public string value; public string value;

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

@ -65,6 +65,19 @@ namespace UnityScript2CSharp.Tests
AssertConversion(sources, expectedConverted); 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] [Test]
public void Additional_Imports() 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; using Boo.Lang.Compiler.TypeSystem;
namespace UnityScript2CSharp.Extensions namespace UnityScript2CSharp.Extensions
@ -10,7 +11,7 @@ namespace UnityScript2CSharp.Extensions
if (node.NodeType != NodeType.MethodInvocationExpression) if (node.NodeType != NodeType.MethodInvocationExpression)
return false; return false;
var invocation = (MethodInvocationExpression) node; var invocation = (MethodInvocationExpression)node;
return invocation.Target.Entity != null && invocation.Target.Entity.EntityType == EntityType.Constructor; return invocation.Target.Entity != null && invocation.Target.Entity.EntityType == EntityType.Constructor;
} }
@ -19,10 +20,15 @@ namespace UnityScript2CSharp.Extensions
if (node.NodeType != NodeType.GenericReferenceExpression) if (node.NodeType != NodeType.GenericReferenceExpression)
return false; return false;
var gre = (GenericReferenceExpression) node; var gre = (GenericReferenceExpression)node;
// Arrays in UnityScript are represented as a GenericReferenceExpession // Arrays in UnityScript are represented as a GenericReferenceExpession
var target = gre.Target as ReferenceExpression; var target = gre.Target as ReferenceExpression;
return target != null && target.Name == "array"; 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\ApplyEnumToImplicitConversions.cs" />
<Compile Include="Steps\ExpandAssignmentToValueTypeMembers.cs" /> <Compile Include="Steps\ExpandAssignmentToValueTypeMembers.cs" />
<Compile Include="Steps\InferredMethodReturnTypeFix.cs" /> <Compile Include="Steps\InferredMethodReturnTypeFix.cs" />
<Compile Include="Steps\InstanceToTypeReferencedStaticMemberReference.cs" />
<Compile Include="Steps\PromoteImplicitBooleanConversionsToExplicitComparisons.cs" /> <Compile Include="Steps\PromoteImplicitBooleanConversionsToExplicitComparisons.cs" />
<Compile Include="Steps\InjectTypeOfExpressionsInArgumentsOfSystemType.cs" /> <Compile Include="Steps\InjectTypeOfExpressionsInArgumentsOfSystemType.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />

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

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

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

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