From 8b20d721b4837c98c75b8c4f1563f145e8769803 Mon Sep 17 00:00:00 2001 From: ydanila Date: Wed, 25 Feb 2015 20:19:50 +0300 Subject: [PATCH 01/37] Another way to get current directory --- src/main/sharpen/core/ConfigurationFactory.java | 11 +++++------ .../sharpen/ui/tests/CustomConfigurationTestCase.java | 5 ++--- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/main/sharpen/core/ConfigurationFactory.java b/src/main/sharpen/core/ConfigurationFactory.java index 82d7e11..1d9177a 100644 --- a/src/main/sharpen/core/ConfigurationFactory.java +++ b/src/main/sharpen/core/ConfigurationFactory.java @@ -73,13 +73,12 @@ public static Configuration newExternalConfiguration(String configurationClass, String configJar = NameUtility.unqualify(configurationClass)+ ".sharpenconfig.jar"; try { - URI currentDirectoryURI = getCurrentDirectoryURI(); - File currentDirectory = new File(currentDirectoryURI); - Path configPath = Paths.get(currentDirectory.getPath(), configJar); + Path currentDirectoryPath = getCurrentDirectory(); + Path configPath = Paths.get(currentDirectoryPath.toString(), configJar); URI jarURI = configPath.toUri(); File configFile = configPath.toFile(); if(!configFile.exists()){ - progressMonitor.subTask("Configuration library " + configJar + " not found"); + progressMonitor.subTask("Configuration library " + configPath); return null; } @@ -90,8 +89,8 @@ public static Configuration newExternalConfiguration(String configurationClass, } } - public static URI getCurrentDirectoryURI() throws URISyntaxException { - return ConfigurationFactory.class.getProtectionDomain().getCodeSource().getLocation().toURI(); + public static Path getCurrentDirectory() throws URISyntaxException { + return Paths.get(".").toAbsolutePath().normalize(); } private static String evalRuntimeType(String runtimeTypeName) { diff --git a/src/test/sharpen/ui/tests/CustomConfigurationTestCase.java b/src/test/sharpen/ui/tests/CustomConfigurationTestCase.java index 181ecba..8a8f004 100644 --- a/src/test/sharpen/ui/tests/CustomConfigurationTestCase.java +++ b/src/test/sharpen/ui/tests/CustomConfigurationTestCase.java @@ -77,10 +77,9 @@ public void worked(int i) { private static Path createConfigurationJar(Class configurationClass) throws Exception { String jar = JarUtilities.createJar(configurationClass); - URI currentDirectoryURI = ConfigurationFactory.getCurrentDirectoryURI(); - File currentDirectory = new File(currentDirectoryURI); + Path currentDirectory = ConfigurationFactory.getCurrentDirectory(); String configJar = configurationClass.getSimpleName()+ ".sharpenconfig.jar"; - Path configPath = Paths.get(currentDirectory.getPath(), configJar); + Path configPath = Paths.get(currentDirectory.toString(), configJar); tryDelete(configPath); Files.move(Paths.get(jar), configPath); return configPath; From 060bd16e408de2d06a4e4355c8e3638db6d9a6af Mon Sep 17 00:00:00 2001 From: ydanila Date: Fri, 27 Feb 2015 12:27:53 +0300 Subject: [PATCH 02/37] Test for annotations renaming --- .../testcases/annotations/SimpleAnnotationMapping.cs.txt | 8 ++++++++ .../annotations/SimpleAnnotationMapping.java.txt | 9 +++++++++ src/test/sharpen/ui/tests/AnnotationsTestCase.java | 6 ++++++ 3 files changed, 23 insertions(+) create mode 100644 sharpen.ui.tests/testcases/annotations/SimpleAnnotationMapping.cs.txt create mode 100644 sharpen.ui.tests/testcases/annotations/SimpleAnnotationMapping.java.txt diff --git a/sharpen.ui.tests/testcases/annotations/SimpleAnnotationMapping.cs.txt b/sharpen.ui.tests/testcases/annotations/SimpleAnnotationMapping.cs.txt new file mode 100644 index 0000000..51ee235 --- /dev/null +++ b/sharpen.ui.tests/testcases/annotations/SimpleAnnotationMapping.cs.txt @@ -0,0 +1,8 @@ +namespace annotations +{ + internal class Annotated + { + [annotations.MappedAnnotation] + public string field; + } +} \ No newline at end of file diff --git a/sharpen.ui.tests/testcases/annotations/SimpleAnnotationMapping.java.txt b/sharpen.ui.tests/testcases/annotations/SimpleAnnotationMapping.java.txt new file mode 100644 index 0000000..c758583 --- /dev/null +++ b/sharpen.ui.tests/testcases/annotations/SimpleAnnotationMapping.java.txt @@ -0,0 +1,9 @@ +package annotations; + +@interface AnnotationToMap { +} + +class Annotated { + @AnnotationToMap + public String field; +} \ No newline at end of file diff --git a/src/test/sharpen/ui/tests/AnnotationsTestCase.java b/src/test/sharpen/ui/tests/AnnotationsTestCase.java index bcefb17..deedcad 100644 --- a/src/test/sharpen/ui/tests/AnnotationsTestCase.java +++ b/src/test/sharpen/ui/tests/AnnotationsTestCase.java @@ -13,6 +13,11 @@ public class AnnotationsTestCase extends AbstractConversionTestCase { public void testSimpleAnnotation() throws IOException, CoreException { runResourceTestCase("SimpleAnnotation"); } + + @Test + public void testSimpleAnnotationMapping() throws IOException, CoreException { + runResourceTestCase("SimpleAnnotationMapping"); + } @Test public void testCompilerAnnotations() throws IOException, CoreException { @@ -28,6 +33,7 @@ protected void runResourceTestCase(String resourceName) throws IOException, Core protected Configuration getConfiguration() { final Configuration config = super.getConfiguration(); config.enableNativeInterfaces(); + config.mapType("annotations.AnnotationToMap", "annotations.MappedAnnotation"); return config; } } From 82cbaf9129085f38f3ab74b2845f42780c2bc408 Mon Sep 17 00:00:00 2001 From: ydanila Date: Fri, 27 Feb 2015 14:49:52 +0300 Subject: [PATCH 03/37] Support for method params annotations --- .../csharp/ast/CSAttributesContainer.java | 12 +++++++ .../core/csharp/ast/CSVariableAttribute.java | 13 ++++++++ .../annotations/MethodAnnotation.cs.txt | 10 ++++++ .../annotations/MethodAnnotation.java.txt | 13 ++++++++ src/main/sharpen/core/CSharpBuilder.java | 16 ++++++---- .../sharpen/core/csharp/CSharpPrinter.java | 19 ++++++++--- .../sharpen/core/csharp/ast/CSAttribute.java | 3 ++ .../sharpen/core/csharp/ast/CSMember.java | 11 ++++--- .../csharp/ast/CSVariableDeclaration.java | 32 +++++++++++++++++-- .../sharpen/ui/tests/AnnotationsTestCase.java | 5 +++ 10 files changed, 116 insertions(+), 18 deletions(-) create mode 100644 sharpen.core/src/sharpen/core/csharp/ast/CSAttributesContainer.java create mode 100644 sharpen.core/src/sharpen/core/csharp/ast/CSVariableAttribute.java create mode 100644 sharpen.ui.tests/testcases/annotations/MethodAnnotation.cs.txt create mode 100644 sharpen.ui.tests/testcases/annotations/MethodAnnotation.java.txt diff --git a/sharpen.core/src/sharpen/core/csharp/ast/CSAttributesContainer.java b/sharpen.core/src/sharpen/core/csharp/ast/CSAttributesContainer.java new file mode 100644 index 0000000..ce27ce3 --- /dev/null +++ b/sharpen.core/src/sharpen/core/csharp/ast/CSAttributesContainer.java @@ -0,0 +1,12 @@ +package sharpen.core.csharp.ast; + +import java.util.List; + +public interface CSAttributesContainer { + + void addAttribute(CSAttribute attribute); + + boolean removeAttribute(String name); + + List attributes(); +} diff --git a/sharpen.core/src/sharpen/core/csharp/ast/CSVariableAttribute.java b/sharpen.core/src/sharpen/core/csharp/ast/CSVariableAttribute.java new file mode 100644 index 0000000..4587b75 --- /dev/null +++ b/sharpen.core/src/sharpen/core/csharp/ast/CSVariableAttribute.java @@ -0,0 +1,13 @@ +package sharpen.core.csharp.ast; + +public class CSVariableAttribute extends CSAttribute { + + public CSVariableAttribute(String attributeName) { + super(attributeName); + } + + @Override + public boolean isParameter() { + return true; + } +} diff --git a/sharpen.ui.tests/testcases/annotations/MethodAnnotation.cs.txt b/sharpen.ui.tests/testcases/annotations/MethodAnnotation.cs.txt new file mode 100644 index 0000000..8e666fe --- /dev/null +++ b/sharpen.ui.tests/testcases/annotations/MethodAnnotation.cs.txt @@ -0,0 +1,10 @@ +namespace annotations +{ + internal class Annotated + { + [annotations.TestAnnotation] + public virtual void annotatedMethod([annotations.NotNull]string name) + { + } + } +} \ No newline at end of file diff --git a/sharpen.ui.tests/testcases/annotations/MethodAnnotation.java.txt b/sharpen.ui.tests/testcases/annotations/MethodAnnotation.java.txt new file mode 100644 index 0000000..ff8a027 --- /dev/null +++ b/sharpen.ui.tests/testcases/annotations/MethodAnnotation.java.txt @@ -0,0 +1,13 @@ +package annotations; + +@interface TestAnnotation { +} + +@interface NotNull { +} + +class Annotated { + @TestAnnotation + public void annotatedMethod(@NotNull String name){ + } +} \ No newline at end of file diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index f72f446..2ee0ea6 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -1491,13 +1491,13 @@ private CSField mapFieldDeclarationFragment(FieldDeclaration node, VariableDecla } else { processFieldModifiers(field, node.getModifiers()); } - mapAnnotations(node, field); + mapAnnotations(node.modifiers(), field); mapDocumentation(node, field); return field; } - private void mapAnnotations(BodyDeclaration node, CSMember member) { - for (Object m : node.modifiers()) { + private void mapAnnotations(List modifiers, CSAttributesContainer member) { + for (Object m : modifiers) { if (!(m instanceof Annotation)) { continue; } @@ -1514,7 +1514,7 @@ private boolean isIgnoredAnnotation(Annotation m) { return _configuration.isIgnoredAnnotation(qualifiedName(m.resolveAnnotationBinding().getAnnotationType())); } - private void mapMarkerAnnotation(MarkerAnnotation annotation, CSMember member) { + private void mapMarkerAnnotation(MarkerAnnotation annotation, CSAttributesContainer member) { final IAnnotationBinding binding = annotation.resolveAnnotationBinding(); final CSAttribute attribute = new CSAttribute(mappedTypeName(binding.getAnnotationType())); member.addAttribute(attribute); @@ -1800,7 +1800,7 @@ private void mapMethodParts(MethodDeclaration node, CSMethodBase method) { method.startPosition(node.getStartPosition()); method.isVarArgs(node.isVarargs()); mapParameters(node, method); - mapAnnotations(node, method); + mapAnnotations(node.modifiers(), method); mapDocumentation(node, method); visitBodyDeclarationBlock(node, node.getBody(), method); @@ -2835,7 +2835,7 @@ public boolean visit(EnumConstantDeclaration node) { CSField field = new CSField(fieldName(node), typeName, visibility, initializer); field.addModifier(CSFieldModifier.Static); field.addModifier(CSFieldModifier.Readonly); - mapAnnotations(node, field); + mapAnnotations(node.modifiers(), field); mapDocumentation(node, field); popExpectedType(saved); @@ -3745,7 +3745,9 @@ private CSExpression popExpression() { } private CSVariableDeclaration createParameter(SingleVariableDeclaration declaration) { - return createVariableDeclaration(declaration.resolveBinding(), null); + CSVariableDeclaration varDeclaration = createVariableDeclaration(declaration.resolveBinding(), null); + mapAnnotations(declaration.modifiers(), varDeclaration); + return varDeclaration; } protected void visit(List nodes) { diff --git a/src/main/sharpen/core/csharp/CSharpPrinter.java b/src/main/sharpen/core/csharp/CSharpPrinter.java index 58c879f..d90dee1 100644 --- a/src/main/sharpen/core/csharp/CSharpPrinter.java +++ b/src/main/sharpen/core/csharp/CSharpPrinter.java @@ -305,6 +305,7 @@ private boolean isExplicitMember(CSMember member) { } public void visit(CSVariableDeclaration node) { + writeAttributes(node); node.type().accept(this); if (null != node.name()) { write(" "); @@ -878,14 +879,24 @@ private void writeMemberBlock(String name, CSBlock block, boolean isAbstract) { } public void visit(CSAttribute node) { - writeIndented("["); + if(node.isParameter()) { + write("["); + } + else { + writeIndented("["); + } write(node.name()); if (!node.arguments().isEmpty()) { writeParameterList(node.arguments()); } - writeLine("]"); + if(node.isParameter()) { + write("]"); + } + else { + writeLine("]"); + } } - + @Override public void visit(CSLabelStatement node) { //labels can't be free-standing, for simplicity simply emit an empty statement @@ -956,7 +967,7 @@ public void visit(CSDocTagNode node) { } } - private void writeAttributes(CSMember node) { + private void writeAttributes(CSAttributesContainer node) { visitList(node.attributes()); } diff --git a/src/main/sharpen/core/csharp/ast/CSAttribute.java b/src/main/sharpen/core/csharp/ast/CSAttribute.java index a5cb837..587cecb 100644 --- a/src/main/sharpen/core/csharp/ast/CSAttribute.java +++ b/src/main/sharpen/core/csharp/ast/CSAttribute.java @@ -37,4 +37,7 @@ public void accept(CSVisitor visitor) { visitor.visit(this); } + public boolean isParameter() { + return false; + } } diff --git a/src/main/sharpen/core/csharp/ast/CSMember.java b/src/main/sharpen/core/csharp/ast/CSMember.java index fd95bdd..e193b35 100644 --- a/src/main/sharpen/core/csharp/ast/CSMember.java +++ b/src/main/sharpen/core/csharp/ast/CSMember.java @@ -29,7 +29,7 @@ import java.util.Collections; import java.util.List; -public abstract class CSMember extends CSNode { +public abstract class CSMember extends CSNode implements CSAttributesContainer { protected String _name; @@ -73,11 +73,13 @@ public List docs() { return Collections.unmodifiableList(_docs); } - public void addAttribute(CSAttribute attribute) { + @Override + public void addAttribute(CSAttribute attribute) { _attributes.add(attribute); } - public boolean removeAttribute (String name) { + @Override + public boolean removeAttribute(String name) { for (CSAttribute at : _attributes) { if (at.name().equals(name)) { _attributes.remove(at); @@ -87,7 +89,8 @@ public boolean removeAttribute (String name) { return false; } - public List attributes() { + @Override + public List attributes() { return Collections.unmodifiableList(_attributes); } diff --git a/src/main/sharpen/core/csharp/ast/CSVariableDeclaration.java b/src/main/sharpen/core/csharp/ast/CSVariableDeclaration.java index 7a30e6e..a328ab4 100644 --- a/src/main/sharpen/core/csharp/ast/CSVariableDeclaration.java +++ b/src/main/sharpen/core/csharp/ast/CSVariableDeclaration.java @@ -21,13 +21,18 @@ package sharpen.core.csharp.ast; -public class CSVariableDeclaration extends CSNode { +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class CSVariableDeclaration extends CSNode implements CSAttributesContainer { private String _name; private CSTypeReferenceExpression _type; private CSExpression _initializer; - - public CSVariableDeclaration(String name, CSTypeReferenceExpression type) { + private List _attributes = new ArrayList(); + + public CSVariableDeclaration(String name, CSTypeReferenceExpression type) { this(name, type, null); } @@ -64,4 +69,25 @@ public CSExpression initializer() { public void name(String name) { _name = name; } + + @Override + public void addAttribute(CSAttribute attribute) { + _attributes.add(new CSVariableAttribute(attribute.name())); + } + + @Override + public boolean removeAttribute(String name) { + for (CSAttribute at : _attributes) { + if (at.name().equals(name)) { + _attributes.remove(at); + return true; + } + } + return false; + } + + @Override + public List attributes() { + return Collections.unmodifiableList(_attributes); + } } diff --git a/src/test/sharpen/ui/tests/AnnotationsTestCase.java b/src/test/sharpen/ui/tests/AnnotationsTestCase.java index deedcad..c581279 100644 --- a/src/test/sharpen/ui/tests/AnnotationsTestCase.java +++ b/src/test/sharpen/ui/tests/AnnotationsTestCase.java @@ -18,6 +18,11 @@ public void testSimpleAnnotation() throws IOException, CoreException { public void testSimpleAnnotationMapping() throws IOException, CoreException { runResourceTestCase("SimpleAnnotationMapping"); } + + @Test + public void testMethodAnnotationMapping() throws IOException, CoreException { + runResourceTestCase("MethodAnnotation"); + } @Test public void testCompilerAnnotations() throws IOException, CoreException { From ee965b87fd59ef2f0eb283930a6510f9f8db1f2d Mon Sep 17 00:00:00 2001 From: ydanila Date: Fri, 27 Feb 2015 17:33:19 +0300 Subject: [PATCH 04/37] Fix for the generics with attributes Test data with var args --- .../annotations/MethodAnnotation.cs.txt | 7 ++++++- .../annotations/MethodAnnotation.java.txt | 3 +++ src/main/sharpen/core/CSharpBuilder.java | 2 +- .../sharpen/core/csharp/CSharpPrinter.java | 20 ++++++++----------- .../sharpen/core/csharp/ast/CSMethodBase.java | 10 ---------- .../csharp/ast/CSVariableDeclaration.java | 9 +++++++++ .../resources/generics/GenericClass.cs.txt | 4 ++++ .../resources/generics/GenericClass.java.txt | 3 +++ 8 files changed, 34 insertions(+), 24 deletions(-) diff --git a/sharpen.ui.tests/testcases/annotations/MethodAnnotation.cs.txt b/sharpen.ui.tests/testcases/annotations/MethodAnnotation.cs.txt index 8e666fe..36b5a70 100644 --- a/sharpen.ui.tests/testcases/annotations/MethodAnnotation.cs.txt +++ b/sharpen.ui.tests/testcases/annotations/MethodAnnotation.cs.txt @@ -3,7 +3,12 @@ namespace annotations internal class Annotated { [annotations.TestAnnotation] - public virtual void annotatedMethod([annotations.NotNull]string name) + public virtual void annotatedMethod([annotations.NotNull] string name) + { + } + + public virtual void annotatedMethodWithVarAgs([annotations.NotNull] params string + [] names) { } } diff --git a/sharpen.ui.tests/testcases/annotations/MethodAnnotation.java.txt b/sharpen.ui.tests/testcases/annotations/MethodAnnotation.java.txt index ff8a027..a93c00d 100644 --- a/sharpen.ui.tests/testcases/annotations/MethodAnnotation.java.txt +++ b/sharpen.ui.tests/testcases/annotations/MethodAnnotation.java.txt @@ -10,4 +10,7 @@ class Annotated { @TestAnnotation public void annotatedMethod(@NotNull String name){ } + + public void annotatedMethodWithVarAgs(@NotNull String... names){ + } } \ No newline at end of file diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 2ee0ea6..7637217 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -1798,7 +1798,6 @@ private void mapMethodParts(MethodDeclaration node, CSMethodBase method) { _currentType.addMember(method); method.startPosition(node.getStartPosition()); - method.isVarArgs(node.isVarargs()); mapParameters(node, method); mapAnnotations(node.modifiers(), method); mapDocumentation(node, method); @@ -3746,6 +3745,7 @@ private CSExpression popExpression() { private CSVariableDeclaration createParameter(SingleVariableDeclaration declaration) { CSVariableDeclaration varDeclaration = createVariableDeclaration(declaration.resolveBinding(), null); + varDeclaration.isVarArgs(declaration.isVarargs()); mapAnnotations(declaration.modifiers(), varDeclaration); return varDeclaration; } diff --git a/src/main/sharpen/core/csharp/CSharpPrinter.java b/src/main/sharpen/core/csharp/CSharpPrinter.java index d90dee1..2e7b189 100644 --- a/src/main/sharpen/core/csharp/CSharpPrinter.java +++ b/src/main/sharpen/core/csharp/CSharpPrinter.java @@ -305,7 +305,13 @@ private boolean isExplicitMember(CSMember member) { } public void visit(CSVariableDeclaration node) { - writeAttributes(node); + if(node.attributes().size() > 0) { + writeAttributes(node); + write(" "); + } + if(node.isVarArgs()) { + write("params "); + } node.type().accept(this); if (null != node.name()) { write(" "); @@ -787,18 +793,8 @@ public void visit(CSMemberReferenceExpression node) { } protected void writeParameterList(CSMethodBase node) { - List parameters = node.parameters(); write("("); - if (node.isVarArgs()) { - if (parameters.size() > 1) { - writeCommaSeparatedList(parameters.subList(0, parameters.size()-1)); - write(", "); - } - write("params "); - visit(parameters.get(parameters.size()-1)); - } else { - writeCommaSeparatedList(parameters); - } + writeCommaSeparatedList(node.parameters()); write(")"); } diff --git a/src/main/sharpen/core/csharp/ast/CSMethodBase.java b/src/main/sharpen/core/csharp/ast/CSMethodBase.java index 7c182c3..aab7343 100644 --- a/src/main/sharpen/core/csharp/ast/CSMethodBase.java +++ b/src/main/sharpen/core/csharp/ast/CSMethodBase.java @@ -31,8 +31,6 @@ public abstract class CSMethodBase extends CSMember implements CSParameterized { private CSBlock _body = new CSBlock(); - private boolean _isVarArgs; - public CSMethodBase(String name) { super(name); } @@ -75,12 +73,4 @@ public String signature() { buffer.append(")"); return buffer.toString(); } - - public void isVarArgs(boolean value) { - _isVarArgs = value; - } - - public boolean isVarArgs() { - return _isVarArgs; - } } diff --git a/src/main/sharpen/core/csharp/ast/CSVariableDeclaration.java b/src/main/sharpen/core/csharp/ast/CSVariableDeclaration.java index a328ab4..79c2628 100644 --- a/src/main/sharpen/core/csharp/ast/CSVariableDeclaration.java +++ b/src/main/sharpen/core/csharp/ast/CSVariableDeclaration.java @@ -31,6 +31,7 @@ public class CSVariableDeclaration extends CSNode implements CSAttributesContain private CSTypeReferenceExpression _type; private CSExpression _initializer; private List _attributes = new ArrayList(); + private boolean _isVarArgs; public CSVariableDeclaration(String name, CSTypeReferenceExpression type) { this(name, type, null); @@ -90,4 +91,12 @@ public boolean removeAttribute(String name) { public List attributes() { return Collections.unmodifiableList(_attributes); } + + public void isVarArgs(boolean isVarArgs) { + _isVarArgs = isVarArgs; + } + + public boolean isVarArgs() { + return _isVarArgs; + } } diff --git a/src/test/resources/generics/GenericClass.cs.txt b/src/test/resources/generics/GenericClass.cs.txt index ee8b459..1959fac 100644 --- a/src/test/resources/generics/GenericClass.cs.txt +++ b/src/test/resources/generics/GenericClass.cs.txt @@ -9,6 +9,10 @@ namespace generics _field1 = f1; } + public virtual void varArgs(params T1[] f1) + { + } + public virtual T1 field1() { return _field1; diff --git a/src/test/resources/generics/GenericClass.java.txt b/src/test/resources/generics/GenericClass.java.txt index 57dda12..008e59a 100644 --- a/src/test/resources/generics/GenericClass.java.txt +++ b/src/test/resources/generics/GenericClass.java.txt @@ -6,6 +6,9 @@ public class GenericClass { public GenericClass(T1 f1) { _field1 = f1; } + + public void varArgs(T1... f1) { + } public T1 field1() { return _field1; From 442fbb1e0d00a38a228d9bb43215cd665aed6343 Mon Sep 17 00:00:00 2001 From: ydanila Date: Fri, 27 Feb 2015 21:04:51 +0300 Subject: [PATCH 05/37] Fix for the enum with instance fields --- sharpen.ui.tests/testcases/Enum2.cs.txt | 12 ++++++++++++ sharpen.ui.tests/testcases/Enum2.java.txt | 12 ++++++++++++ src/main/sharpen/core/CSharpBuilder.java | 2 +- .../ui/tests/UnclassifiedConversionTestCase.java | 5 +++++ 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 sharpen.ui.tests/testcases/Enum2.cs.txt create mode 100644 sharpen.ui.tests/testcases/Enum2.java.txt diff --git a/sharpen.ui.tests/testcases/Enum2.cs.txt b/sharpen.ui.tests/testcases/Enum2.cs.txt new file mode 100644 index 0000000..4ff5253 --- /dev/null +++ b/sharpen.ui.tests/testcases/Enum2.cs.txt @@ -0,0 +1,12 @@ +[System.Serializable] +public sealed class Enum2 +{ + public static readonly Enum2 EnumValue = new Enum2(0); + + private readonly int _instanceField; + + private Enum2(int value) + { + _instanceField = value; + } +} \ No newline at end of file diff --git a/sharpen.ui.tests/testcases/Enum2.java.txt b/sharpen.ui.tests/testcases/Enum2.java.txt new file mode 100644 index 0000000..e3800ee --- /dev/null +++ b/sharpen.ui.tests/testcases/Enum2.java.txt @@ -0,0 +1,12 @@ + +public enum Enum2 +{ + EnumValue(0); + + private final int _instanceField; + + private Enum2(int value) + { + _instanceField = value; + } +} diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 7637217..09190aa 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -3551,7 +3551,7 @@ public boolean visit(SimpleName node) { return false; } } - else if (cls.isEnum() && ident.indexOf('.') == -1){ + else if (cls.isEnum() && ident.indexOf('.') == -1 && vb.isEnumConstant()){ pushExpression(new CSMemberReferenceExpression(mappedTypeReference(cls), ident)); return false; } diff --git a/src/test/sharpen/ui/tests/UnclassifiedConversionTestCase.java b/src/test/sharpen/ui/tests/UnclassifiedConversionTestCase.java index d906ae1..47a3ec4 100644 --- a/src/test/sharpen/ui/tests/UnclassifiedConversionTestCase.java +++ b/src/test/sharpen/ui/tests/UnclassifiedConversionTestCase.java @@ -45,6 +45,11 @@ public void testVarArgs() throws Throwable { public void testSharpenEnum() throws Throwable { runResourceTestCase("Enum1"); } + + @Test + public void testSharpenEnumClass() throws Throwable { + runResourceTestCase("Enum2"); + } @Test public void testObjectMethodsThroughGenericInterface() throws Throwable { From fa673fe955a6cae67e52dee1a8f1b043fa0dba75 Mon Sep 17 00:00:00 2001 From: ydanila Date: Sat, 28 Feb 2015 15:46:56 +0300 Subject: [PATCH 06/37] More flexible behaviour for the Sharpen with new extra CLI switches --- src/main/sharpen/core/Configuration.java | 54 +++++++++++++++--- .../sharpen/core/DefaultConfiguration.java | 55 +++++++++++++++---- src/main/sharpen/core/SharpenApplication.java | 21 ++++++- src/main/sharpen/core/SharpenCommandLine.java | 9 ++- .../core/SharpenCommandLineParser.java | 22 ++++++-- 5 files changed, 134 insertions(+), 27 deletions(-) diff --git a/src/main/sharpen/core/Configuration.java b/src/main/sharpen/core/Configuration.java index 1db5210..98439d0 100644 --- a/src/main/sharpen/core/Configuration.java +++ b/src/main/sharpen/core/Configuration.java @@ -27,7 +27,14 @@ public abstract class Configuration { - public static class MemberMapping { + // default mapping enabled + private boolean _mapIteratorToEnumerator = true; + // default mapping disabled + private boolean _mapByteToSbyte = false; + // default getter disabled + private boolean _numberValueGetter = false; + + public static class MemberMapping { public String name; public MemberKind kind; @@ -189,7 +196,7 @@ protected void setUpIoMappings() { mapType("java.io.StringWriter", "System.IO.StringWriter"); mapMethod("java.io.PrintStream.print", "Write"); - mapMethod("java.io.PrintStream.println", "WriteLine"); + mapMethod("java.io.PrintStream.println", "WriteLine"); } protected String collectionRuntimeMethod(String methodName) { @@ -363,7 +370,11 @@ public String getConvertRelatedWellKnownTypeName(String mappedConstructor) { public void mapType(String from, String to) { _typeMappings.put(from, to); } - + + protected void unmapType(String from) { + _typeMappings.remove(from); + } + public boolean typeHasMapping(String type) { return _typeMappings.containsKey(type); } @@ -375,6 +386,10 @@ public void mapField(String fromQualifiedName, String to) { public void mapMethod(String fromQualifiedName, String to) { mapMember(fromQualifiedName, new MemberMapping(to, MemberKind.Method)); } + + protected void unmapMethod(String fromQualifiedName) { + unmapMember(fromQualifiedName); + } public void mapIndexer(String fromQualifiedName) { mapMember(fromQualifiedName, new MemberMapping(null, MemberKind.Indexer)); @@ -383,8 +398,12 @@ public void mapIndexer(String fromQualifiedName) { public void mapProperty(String fromQualifiedName, String to) { mapMember(fromQualifiedName, new MemberMapping(to, MemberKind.Property)); } - - public void setIgnoreErrors(boolean value) { + + protected void unmapProperty(String fromQualifiedName) { + unmapMember(fromQualifiedName); + } + + public void setIgnoreErrors(boolean value) { _ignoreErrors = value; } @@ -396,6 +415,10 @@ void mapMember(String fromQualifiedName, MemberMapping mapping) { _memberMappings.put(fromQualifiedName, mapping); } + protected void unmapMember(String fromQualifiedName) { + _memberMappings.remove(fromQualifiedName); + } + protected void mapWrapperConstructor(String from, String to, String wellKnownTypeName) { mapMethod(from, to); _systemConvertWellKnownTypes.put(to, wellKnownTypeName); @@ -562,9 +585,26 @@ public boolean mapProtectedToProtectedInternal() { } public boolean mapIteratorToEnumerator() { - return true; + return _mapIteratorToEnumerator; } - public abstract boolean mapByteToSbyte(); + public void disableMapIteratorToEnumerator() { + _mapIteratorToEnumerator = false; + } + + public boolean mapByteToSbyte(){ + return _mapByteToSbyte; + } + + public void enableMapByteToSbyte(){ + _mapByteToSbyte = true; + } + public boolean numberValueGetter(){ + return _numberValueGetter; + } + + public void enableNumberValueGetter(){ + _numberValueGetter = true; + } } diff --git a/src/main/sharpen/core/DefaultConfiguration.java b/src/main/sharpen/core/DefaultConfiguration.java index 41bc47d..4a90858 100644 --- a/src/main/sharpen/core/DefaultConfiguration.java +++ b/src/main/sharpen/core/DefaultConfiguration.java @@ -252,12 +252,14 @@ private void setUpPrimitiveWrappers() { mapMethod("java.lang.Long.parseLong", "long.Parse"); mapMethod("java.lang.Integer.valueOf", "int.Parse"); mapMethod("java.lang.Integer.parseInt", "System.Convert.ToInt32"); - mapMethod("java.lang.Number.shortValue", ""); - mapMethod("java.lang.Number.intValue", ""); - mapMethod("java.lang.Number.longValue", ""); - mapMethod("java.lang.Number.byteValue", ""); - mapMethod("java.lang.Number.floatValue", ""); - mapMethod("java.lang.Number.doubleValue", ""); + if(!numberValueGetter()) { + mapMethod("java.lang.Number.shortValue", ""); + mapMethod("java.lang.Number.intValue", ""); + mapMethod("java.lang.Number.longValue", ""); + mapMethod("java.lang.Number.byteValue", ""); + mapMethod("java.lang.Number.floatValue", ""); + mapMethod("java.lang.Number.doubleValue", ""); + } mapMethod("java.lang.Character.charValue", ""); mapMethod("java.lang.Boolean.booleanValue", ""); mapMethod("java.lang.Float.floatToIntBits", runtimeMethod("floatToIntBits")); @@ -266,11 +268,40 @@ private void setUpPrimitiveWrappers() { public boolean isIgnoredExceptionType(String exceptionType) { return exceptionType.equals("java.lang.CloneNotSupportedException"); - } - - @Override - public boolean mapByteToSbyte() { - return false; } -} + @Override + public void enableMapByteToSbyte() { + super.enableMapByteToSbyte(); + mapType("byte", "sbyte"); + mapType("java.lang.Byte", "sbyte"); + mapField("java.lang.Byte.MAX_VALUE", "sbyte.MaxValue"); + mapField("java.lang.Byte.MIN_VALUE", "sbyte.MinValue"); + } + + @Override + public void disableMapIteratorToEnumerator() { + super.disableMapIteratorToEnumerator(); + unmapType("java.util.Iterator"); + unmapType("java.util.Iterator<>"); + unmapType("java.lang.Iterable"); + unmapType("java.lang.Iterable<>"); + unmapMethod("java.lang.Iterable.iterator"); + unmapMethod("java.util.Collection.iterator"); + unmapMethod("java.util.List.iterator"); + unmapMethod("java.util.Set.iterator"); + unmapMethod("java.util.Iterator.hasNext"); + unmapProperty("java.util.Iterator.next"); + } + + @Override + public void enableNumberValueGetter() { + super.enableNumberValueGetter(); + unmapMethod("java.lang.Number.shortValue"); + unmapMethod("java.lang.Number.intValue"); + unmapMethod("java.lang.Number.longValue"); + unmapMethod("java.lang.Number.byteValue"); + unmapMethod("java.lang.Number.floatValue"); + unmapMethod("java.lang.Number.doubleValue"); + } +} \ No newline at end of file diff --git a/src/main/sharpen/core/SharpenApplication.java b/src/main/sharpen/core/SharpenApplication.java index 3de5e90..5d7ba22 100644 --- a/src/main/sharpen/core/SharpenApplication.java +++ b/src/main/sharpen/core/SharpenApplication.java @@ -197,6 +197,18 @@ private Configuration getConfiguration() throws IOException { ods("Organize usings mode on."); configuration.enableOrganizeUsings(); } + if (_args.mapByteToSbyte) { + ods("Mapping byte to sbyte mode on."); + configuration.enableMapByteToSbyte(); + } + if (_args.disableMapIteratorToEnumerator) { + ods("Mapping iterator to enumerator mode off."); + configuration.disableMapIteratorToEnumerator(); + } + if (_args.numberValueGetter) { + ods("Number value getter mode on."); + configuration.enableNumberValueGetter(); + } if (_args.paramCountFileNames) { ods("Generic parameter count appended to file names."); configuration.enableParamCountFileNames(); @@ -234,7 +246,14 @@ private Configuration getConfiguration() throws IOException { for (Configuration.NameMapping mapping : _args.typeMappings) { configuration.mapType(mapping.from, mapping.to); } - return configuration; + + for (String from : _args.removeTypeMappings) { + configuration.unmapType(from); + } + for (String from : _args.removeMemberMappings) { + configuration.unmapMember(from); + } + return configuration; } private List sortedByName(List units) { diff --git a/src/main/sharpen/core/SharpenCommandLine.java b/src/main/sharpen/core/SharpenCommandLine.java index f84e0d9..4f21941 100644 --- a/src/main/sharpen/core/SharpenCommandLine.java +++ b/src/main/sharpen/core/SharpenCommandLine.java @@ -24,8 +24,8 @@ import java.util.*; public class SharpenCommandLine { - - public static SharpenCommandLine parse(String[] args) { + + public static SharpenCommandLine parse(String[] args) { return new SharpenCommandLineParser(args).commandLine(); } @@ -74,9 +74,14 @@ public NamingStrategy getNamingStrategy() { final public List namespaceMappings = new ArrayList(); final public List typeMappings = new ArrayList(); final public Map memberMappings = new HashMap(); + final public List removeTypeMappings = new ArrayList(); + final public List removeMemberMappings = new ArrayList(); public boolean nativeInterfaces; public boolean separateInterfaceConstants; public boolean organizeUsings; + public boolean mapByteToSbyte; + public boolean disableMapIteratorToEnumerator; + public boolean numberValueGetter; public boolean paramCountFileNames; final public List fullyQualifiedTypes = new ArrayList(); final public List partialTypes = new ArrayList(); diff --git a/src/main/sharpen/core/SharpenCommandLineParser.java b/src/main/sharpen/core/SharpenCommandLineParser.java index 6bd3faa..d21f32c 100644 --- a/src/main/sharpen/core/SharpenCommandLineParser.java +++ b/src/main/sharpen/core/SharpenCommandLineParser.java @@ -107,17 +107,23 @@ protected void processOption(String arg) { _cmdLine.organizeUsings = true; } else if (areEqual(arg, "-continueOnError")) { _cmdLine.continueOnError = true; + } else if (areEqual(arg, "-mapByteToSbyte")) { + _cmdLine.mapByteToSbyte = true; + } else if (areEqual(arg, "-disableMapIteratorToEnumerator")) { + _cmdLine.disableMapIteratorToEnumerator = true; + } else if (areEqual(arg, "-numberValueGetter")) { + _cmdLine.numberValueGetter = true; } else if (areEqual(arg, "-fullyQualify")) { _cmdLine.fullyQualifiedTypes.add(consumeNext()); } else if (areEqual(arg, "-namespaceMapping")) { _cmdLine.namespaceMappings.add(consumeNameMapping()); - } else if (areEqual(arg, "-methodMapping")) { + } else if (areEqual(arg, "-methodMapping")) { String from = consumeNext(); String to = consumeNext(); _cmdLine.memberMappings.put(from, new Configuration.MemberMapping(to, MemberKind.Method)); - } else if (areEqual(arg, "-typeMapping")) { + } else if (areEqual(arg, "-typeMapping")) { _cmdLine.typeMappings.add(consumeNameMapping()); - } else if (areEqual(arg, "-propertyMapping")) { + } else if (areEqual(arg, "-propertyMapping")) { String from = consumeNext(); String to = consumeNext(); _cmdLine.memberMappings.put(from, new Configuration.MemberMapping(to, MemberKind.Property)); @@ -128,7 +134,13 @@ protected void processOption(String arg) { } else if (areEqual(arg, "-indexerMapping")) { String from = consumeNext(); _cmdLine.memberMappings.put(from, new Configuration.MemberMapping(null, MemberKind.Indexer)); - } else if (areEqual(arg, "-makePartial")){ + } else if (areEqual(arg, "-removeTypeMapping")) { + String from = consumeNext(); + _cmdLine.removeTypeMappings.add(from); + } else if (areEqual(arg, "-removeMemberMapping")) { + String from = consumeNext(); + _cmdLine.removeMemberMappings.add(from); + } else if (areEqual(arg, "-makePartial")){ _cmdLine.partialTypes.add (consumeNext()); } else if (areEqual(arg, "-runtimeTypeName")){ _cmdLine.runtimeTypeName = consumeNext(); @@ -140,7 +152,7 @@ protected void processOption(String arg) { _cmdLine.eventMappings.add(consumeNameMapping()); } else if (areEqual(arg, "-eventAddMapping")){ _cmdLine.eventAddMappings.add(consumeNext()); - } else if (areEqual(arg, "-conditionalCompilation")) { + } else if (areEqual(arg, "-conditionalCompilation")) { _cmdLine.conditionalCompilation.put(consumeNext(), consumeNext()); } else if (areEqual(arg, "-configurationClass")) { _cmdLine.configurationClass = consumeNext(); From c7dbb53b963cc2ab2863cc33a04b3fc977702b66 Mon Sep 17 00:00:00 2001 From: ydanila Date: Mon, 2 Mar 2015 11:38:11 +0300 Subject: [PATCH 07/37] Test for conversion Java interface to C# class --- .../testcases/interfaces/IInterfaceToClass.cs.txt | 13 +++++++++++++ .../testcases/interfaces/InterfaceToClass.java.txt | 6 ++++++ .../sharpen/ui/tests/NativeInterfacesTestCase.java | 5 +++++ 3 files changed, 24 insertions(+) create mode 100644 sharpen.ui.tests/testcases/interfaces/IInterfaceToClass.cs.txt create mode 100644 sharpen.ui.tests/testcases/interfaces/InterfaceToClass.java.txt diff --git a/sharpen.ui.tests/testcases/interfaces/IInterfaceToClass.cs.txt b/sharpen.ui.tests/testcases/interfaces/IInterfaceToClass.cs.txt new file mode 100644 index 0000000..34500e0 --- /dev/null +++ b/sharpen.ui.tests/testcases/interfaces/IInterfaceToClass.cs.txt @@ -0,0 +1,13 @@ +namespace Interfaces +{ + public abstract class IInterfaceToClass + { + public const int value = 0; + + public abstract void Bar(); + } + + public static class InterfaceToClassConstants + { + } +} \ No newline at end of file diff --git a/sharpen.ui.tests/testcases/interfaces/InterfaceToClass.java.txt b/sharpen.ui.tests/testcases/interfaces/InterfaceToClass.java.txt new file mode 100644 index 0000000..60be6af --- /dev/null +++ b/sharpen.ui.tests/testcases/interfaces/InterfaceToClass.java.txt @@ -0,0 +1,6 @@ +package interfaces; + +public interface InterfaceToClass { + int value = 0; + void bar(); +} diff --git a/src/test/sharpen/ui/tests/NativeInterfacesTestCase.java b/src/test/sharpen/ui/tests/NativeInterfacesTestCase.java index 3b62678..ae65191 100644 --- a/src/test/sharpen/ui/tests/NativeInterfacesTestCase.java +++ b/src/test/sharpen/ui/tests/NativeInterfacesTestCase.java @@ -64,6 +64,11 @@ public void testStubsInDiamondInterfaceInheritance() throws Throwable { runResourceTestCase(newNativeInterfacesConfiguration(), "interfaces/DiamondImpl"); } + @Test + public void testInterfaceConversionToClass() throws Throwable { + runResourceTestCase(newNativeInterfacesConfiguration(), "interfaces/InterfaceToClass", "interfaces/IInterfaceToClass"); + } + public Configuration newNativeInterfacesConfiguration() { Configuration configuration = newPascalCasePlusConfiguration(); configuration.enableNativeInterfaces(); From fa701bb503ac6772583a99b278938a04ce6a006c Mon Sep 17 00:00:00 2001 From: ydanila Date: Mon, 2 Mar 2015 15:00:04 +0300 Subject: [PATCH 08/37] Support for multiple variable declarations in for cycle init section --- sharpen.ui.tests/testcases/For3.cs.txt | 9 +++++++++ sharpen.ui.tests/testcases/For3.java.txt | 6 ++++++ src/main/sharpen/core/CSharpBuilder.java | 11 +++++++++-- src/main/sharpen/core/csharp/CSharpPrinter.java | 10 +++++++--- .../core/csharp/ast/CSDeclarationExpression.java | 16 ++++++++++++---- .../core/csharp/ast/CSVariableDeclaration.java | 9 +++++++++ .../ui/tests/UnclassifiedConversionTestCase.java | 5 +++++ 7 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 sharpen.ui.tests/testcases/For3.cs.txt create mode 100644 sharpen.ui.tests/testcases/For3.java.txt diff --git a/sharpen.ui.tests/testcases/For3.cs.txt b/sharpen.ui.tests/testcases/For3.cs.txt new file mode 100644 index 0000000..3bff49a --- /dev/null +++ b/sharpen.ui.tests/testcases/For3.cs.txt @@ -0,0 +1,9 @@ +public class For3 +{ + public virtual void run(string[] args) + { + for (int j = 1, i = 1; i < 5; ++i, ++j) + { + } + } +} \ No newline at end of file diff --git a/sharpen.ui.tests/testcases/For3.java.txt b/sharpen.ui.tests/testcases/For3.java.txt new file mode 100644 index 0000000..9f92f26 --- /dev/null +++ b/sharpen.ui.tests/testcases/For3.java.txt @@ -0,0 +1,6 @@ +public class For3 { + public void run(String[] args) { + for (int j = 1, i = 1; i<5; ++i, ++j) { + } + } +} \ No newline at end of file diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 09190aa..48cfad3 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -2132,8 +2132,15 @@ private void visitBlock(CSBlock block, T node) { } public boolean visit(VariableDeclarationExpression node) { - pushExpression(new CSDeclarationExpression(createVariableDeclaration((VariableDeclarationFragment) node - .fragments().get(0)))); + List declarations = new ArrayList(); + for(int i = 0; i < node.fragments().size(); i++){ + VariableDeclarationFragment fragment = (VariableDeclarationFragment) node.fragments().get(i); + CSVariableDeclaration variableDeclaraion = createVariableDeclaration(fragment); + // write type declaration only for the first expression + variableDeclaraion.declareType(i == 0); + declarations.add(variableDeclaraion); + } + pushExpression(new CSDeclarationExpression(declarations)); return false; } diff --git a/src/main/sharpen/core/csharp/CSharpPrinter.java b/src/main/sharpen/core/csharp/CSharpPrinter.java index 2e7b189..da9da93 100644 --- a/src/main/sharpen/core/csharp/CSharpPrinter.java +++ b/src/main/sharpen/core/csharp/CSharpPrinter.java @@ -312,9 +312,13 @@ public void visit(CSVariableDeclaration node) { if(node.isVarArgs()) { write("params "); } - node.type().accept(this); + if(node.declareType()) { + node.type().accept(this); + } if (null != node.name()) { - write(" "); + if(node.declareType()) { + write(" "); + } write(node.name()); } if (null != node.initializer()) { @@ -420,7 +424,7 @@ public void visit(CSDeclarationStatement node) { } public void visit(CSDeclarationExpression node) { - node.declaration().accept(this); + writeCommaSeparatedList(node.declarations()); } private void writeDeclaration(CSTypeReferenceExpression type, String name, CSExpression initializer) { diff --git a/src/main/sharpen/core/csharp/ast/CSDeclarationExpression.java b/src/main/sharpen/core/csharp/ast/CSDeclarationExpression.java index 1e5c399..2b8ac06 100644 --- a/src/main/sharpen/core/csharp/ast/CSDeclarationExpression.java +++ b/src/main/sharpen/core/csharp/ast/CSDeclarationExpression.java @@ -21,16 +21,24 @@ package sharpen.core.csharp.ast; +import java.util.ArrayList; +import java.util.List; + public class CSDeclarationExpression extends CSExpression { - private CSVariableDeclaration _declaration; + private List _declarations; public CSDeclarationExpression(CSVariableDeclaration declaration) { - _declaration = declaration; + _declarations = new ArrayList(); + _declarations.add(declaration); } + + public CSDeclarationExpression(List declarations) { + _declarations = declarations; + } - public CSVariableDeclaration declaration() { - return _declaration; + public List declarations() { + return _declarations; } public void accept(CSVisitor visitor) { diff --git a/src/main/sharpen/core/csharp/ast/CSVariableDeclaration.java b/src/main/sharpen/core/csharp/ast/CSVariableDeclaration.java index 79c2628..88ed454 100644 --- a/src/main/sharpen/core/csharp/ast/CSVariableDeclaration.java +++ b/src/main/sharpen/core/csharp/ast/CSVariableDeclaration.java @@ -32,6 +32,7 @@ public class CSVariableDeclaration extends CSNode implements CSAttributesContain private CSExpression _initializer; private List _attributes = new ArrayList(); private boolean _isVarArgs; + private boolean _declareType = true; public CSVariableDeclaration(String name, CSTypeReferenceExpression type) { this(name, type, null); @@ -99,4 +100,12 @@ public void isVarArgs(boolean isVarArgs) { public boolean isVarArgs() { return _isVarArgs; } + + public boolean declareType() { + return _declareType; + } + + public void declareType(boolean declareType) { + _declareType = declareType; + } } diff --git a/src/test/sharpen/ui/tests/UnclassifiedConversionTestCase.java b/src/test/sharpen/ui/tests/UnclassifiedConversionTestCase.java index 47a3ec4..bd6d94b 100644 --- a/src/test/sharpen/ui/tests/UnclassifiedConversionTestCase.java +++ b/src/test/sharpen/ui/tests/UnclassifiedConversionTestCase.java @@ -186,6 +186,11 @@ public void testCharLiteral() throws Throwable { public void testForWithAssignment() throws Throwable { runResourceTestCase("For2"); } + + @Test + public void testForWithMultipleInitializers() throws Throwable { + runResourceTestCase("For3"); + } @Test public void testGetClass() throws Throwable { From cc1abfc77b5a5894c325f009ff02ca3ca4552ad2 Mon Sep 17 00:00:00 2001 From: ydanila Date: Tue, 3 Mar 2015 16:48:27 +0300 Subject: [PATCH 09/37] Test resources moved to the new project structure --- .../main}/sharpen/core/csharp/ast/CSAttributesContainer.java | 0 .../main}/sharpen/core/csharp/ast/CSVariableAttribute.java | 0 {sharpen.ui.tests/testcases => src/test/resources}/Enum2.cs.txt | 0 {sharpen.ui.tests/testcases => src/test/resources}/Enum2.java.txt | 0 {sharpen.ui.tests/testcases => src/test/resources}/For3.cs.txt | 0 {sharpen.ui.tests/testcases => src/test/resources}/For3.java.txt | 0 .../test/resources}/annotations/MethodAnnotation.cs.txt | 0 .../test/resources}/annotations/MethodAnnotation.java.txt | 0 .../test/resources}/annotations/SimpleAnnotationMapping.cs.txt | 0 .../test/resources}/annotations/SimpleAnnotationMapping.java.txt | 0 .../test/resources}/interfaces/IInterfaceToClass.cs.txt | 0 .../test/resources}/interfaces/InterfaceToClass.java.txt | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename {sharpen.core/src => src/main}/sharpen/core/csharp/ast/CSAttributesContainer.java (100%) rename {sharpen.core/src => src/main}/sharpen/core/csharp/ast/CSVariableAttribute.java (100%) rename {sharpen.ui.tests/testcases => src/test/resources}/Enum2.cs.txt (100%) rename {sharpen.ui.tests/testcases => src/test/resources}/Enum2.java.txt (100%) rename {sharpen.ui.tests/testcases => src/test/resources}/For3.cs.txt (100%) rename {sharpen.ui.tests/testcases => src/test/resources}/For3.java.txt (100%) rename {sharpen.ui.tests/testcases => src/test/resources}/annotations/MethodAnnotation.cs.txt (100%) rename {sharpen.ui.tests/testcases => src/test/resources}/annotations/MethodAnnotation.java.txt (100%) rename {sharpen.ui.tests/testcases => src/test/resources}/annotations/SimpleAnnotationMapping.cs.txt (100%) rename {sharpen.ui.tests/testcases => src/test/resources}/annotations/SimpleAnnotationMapping.java.txt (100%) rename {sharpen.ui.tests/testcases => src/test/resources}/interfaces/IInterfaceToClass.cs.txt (100%) rename {sharpen.ui.tests/testcases => src/test/resources}/interfaces/InterfaceToClass.java.txt (100%) diff --git a/sharpen.core/src/sharpen/core/csharp/ast/CSAttributesContainer.java b/src/main/sharpen/core/csharp/ast/CSAttributesContainer.java similarity index 100% rename from sharpen.core/src/sharpen/core/csharp/ast/CSAttributesContainer.java rename to src/main/sharpen/core/csharp/ast/CSAttributesContainer.java diff --git a/sharpen.core/src/sharpen/core/csharp/ast/CSVariableAttribute.java b/src/main/sharpen/core/csharp/ast/CSVariableAttribute.java similarity index 100% rename from sharpen.core/src/sharpen/core/csharp/ast/CSVariableAttribute.java rename to src/main/sharpen/core/csharp/ast/CSVariableAttribute.java diff --git a/sharpen.ui.tests/testcases/Enum2.cs.txt b/src/test/resources/Enum2.cs.txt similarity index 100% rename from sharpen.ui.tests/testcases/Enum2.cs.txt rename to src/test/resources/Enum2.cs.txt diff --git a/sharpen.ui.tests/testcases/Enum2.java.txt b/src/test/resources/Enum2.java.txt similarity index 100% rename from sharpen.ui.tests/testcases/Enum2.java.txt rename to src/test/resources/Enum2.java.txt diff --git a/sharpen.ui.tests/testcases/For3.cs.txt b/src/test/resources/For3.cs.txt similarity index 100% rename from sharpen.ui.tests/testcases/For3.cs.txt rename to src/test/resources/For3.cs.txt diff --git a/sharpen.ui.tests/testcases/For3.java.txt b/src/test/resources/For3.java.txt similarity index 100% rename from sharpen.ui.tests/testcases/For3.java.txt rename to src/test/resources/For3.java.txt diff --git a/sharpen.ui.tests/testcases/annotations/MethodAnnotation.cs.txt b/src/test/resources/annotations/MethodAnnotation.cs.txt similarity index 100% rename from sharpen.ui.tests/testcases/annotations/MethodAnnotation.cs.txt rename to src/test/resources/annotations/MethodAnnotation.cs.txt diff --git a/sharpen.ui.tests/testcases/annotations/MethodAnnotation.java.txt b/src/test/resources/annotations/MethodAnnotation.java.txt similarity index 100% rename from sharpen.ui.tests/testcases/annotations/MethodAnnotation.java.txt rename to src/test/resources/annotations/MethodAnnotation.java.txt diff --git a/sharpen.ui.tests/testcases/annotations/SimpleAnnotationMapping.cs.txt b/src/test/resources/annotations/SimpleAnnotationMapping.cs.txt similarity index 100% rename from sharpen.ui.tests/testcases/annotations/SimpleAnnotationMapping.cs.txt rename to src/test/resources/annotations/SimpleAnnotationMapping.cs.txt diff --git a/sharpen.ui.tests/testcases/annotations/SimpleAnnotationMapping.java.txt b/src/test/resources/annotations/SimpleAnnotationMapping.java.txt similarity index 100% rename from sharpen.ui.tests/testcases/annotations/SimpleAnnotationMapping.java.txt rename to src/test/resources/annotations/SimpleAnnotationMapping.java.txt diff --git a/sharpen.ui.tests/testcases/interfaces/IInterfaceToClass.cs.txt b/src/test/resources/interfaces/IInterfaceToClass.cs.txt similarity index 100% rename from sharpen.ui.tests/testcases/interfaces/IInterfaceToClass.cs.txt rename to src/test/resources/interfaces/IInterfaceToClass.cs.txt diff --git a/sharpen.ui.tests/testcases/interfaces/InterfaceToClass.java.txt b/src/test/resources/interfaces/InterfaceToClass.java.txt similarity index 100% rename from sharpen.ui.tests/testcases/interfaces/InterfaceToClass.java.txt rename to src/test/resources/interfaces/InterfaceToClass.java.txt From d5b30fdb0df302398b81d487859f3bebf02ea6f4 Mon Sep 17 00:00:00 2001 From: ydanila Date: Wed, 11 Mar 2015 11:39:32 +0300 Subject: [PATCH 10/37] Fixed static field import detection --- src/main/sharpen/core/CSharpBuilder.java | 4 +--- src/main/sharpen/core/framework/StaticImports.java | 13 ++++++++----- src/test/resources/imports/StaticImports.cs.txt | 8 +++++++- src/test/resources/imports/StaticImports.java.txt | 5 ++++- .../resources/imports/StaticallyImported.cs.txt | 2 ++ .../resources/imports/StaticallyImported.java.txt | 2 ++ 6 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 48cfad3..f1dcc45 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -3553,10 +3553,8 @@ public boolean visit(SimpleName node) { ITypeBinding cls = vb.getDeclaringClass(); if (cls != null) { if (isStaticImport(vb, _ast.imports())) { - if (cls != null) { pushExpression(new CSMemberReferenceExpression(mappedTypeReference(cls), ident)); return false; - } } else if (cls.isEnum() && ident.indexOf('.') == -1 && vb.isEnumConstant()){ pushExpression(new CSMemberReferenceExpression(mappedTypeReference(cls), ident)); @@ -3573,7 +3571,7 @@ else if (_configuration.separateInterfaceConstants() && cls.isInterface() && ide return false; } - private void addStatement(CSStatement statement) { + private void addStatement(CSStatement statement) { _currentBlock.addStatement(statement); } diff --git a/src/main/sharpen/core/framework/StaticImports.java b/src/main/sharpen/core/framework/StaticImports.java index a1f62da..bf827d1 100644 --- a/src/main/sharpen/core/framework/StaticImports.java +++ b/src/main/sharpen/core/framework/StaticImports.java @@ -23,11 +23,14 @@ public static boolean isStaticMethodImport(ImportDeclaration imp, IMethodBinding } public static boolean isStaticFieldImport(ImportDeclaration imp, IVariableBinding field) { - final IBinding binding = imp.resolveBinding(); - if (binding.getKind() == IBinding.VARIABLE) - return binding == field; - - return false; + final IBinding binding = imp.resolveBinding(); + switch (binding.getKind()) { + case IBinding.TYPE: + return imp.isOnDemand() && field.getDeclaringClass() == binding; + case IBinding.VARIABLE: + return binding == field; + } + return false; } public static boolean isStaticImport(IMethodBinding method, List imports) { diff --git a/src/test/resources/imports/StaticImports.cs.txt b/src/test/resources/imports/StaticImports.cs.txt index 71cc0f8..00004ee 100644 --- a/src/test/resources/imports/StaticImports.cs.txt +++ b/src/test/resources/imports/StaticImports.cs.txt @@ -4,7 +4,13 @@ namespace imports { internal virtual void bar() { - imports.StaticallyImported.foo(); + switch (imports.StaticallyImported.foo()) + { + case imports.StaticallyImported.TAG: + { + break; + } + } } } } \ No newline at end of file diff --git a/src/test/resources/imports/StaticImports.java.txt b/src/test/resources/imports/StaticImports.java.txt index 0fa83d7..2ed37b0 100644 --- a/src/test/resources/imports/StaticImports.java.txt +++ b/src/test/resources/imports/StaticImports.java.txt @@ -5,7 +5,10 @@ import static imports.StaticallyImported.*; class StaticImports { void bar() { - foo(); + switch(foo()){ + case TAG: + break; + } } } \ No newline at end of file diff --git a/src/test/resources/imports/StaticallyImported.cs.txt b/src/test/resources/imports/StaticallyImported.cs.txt index d6d87df..090bcb6 100644 --- a/src/test/resources/imports/StaticallyImported.cs.txt +++ b/src/test/resources/imports/StaticallyImported.cs.txt @@ -2,6 +2,8 @@ namespace imports { internal class StaticallyImported { + public const int TAG = unchecked((int)(0x0003)); + internal static int foo() { return 42; diff --git a/src/test/resources/imports/StaticallyImported.java.txt b/src/test/resources/imports/StaticallyImported.java.txt index 87a3f9a..0521500 100644 --- a/src/test/resources/imports/StaticallyImported.java.txt +++ b/src/test/resources/imports/StaticallyImported.java.txt @@ -2,6 +2,8 @@ package imports; class StaticallyImported { + public static final int TAG = 0x0003; + static int foo() { return 42; } From 4d755ca00f7e689d4214ea1cf802dcd014cb34c4 Mon Sep 17 00:00:00 2001 From: ydanila Date: Wed, 11 Mar 2015 11:59:38 +0300 Subject: [PATCH 11/37] Wrong sharpen.core references replaced by src --- README.md | 4 ++-- src/test/sharpen/ui/tests/AbstractConversionTestCase.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7a17bdc..2b99cd5 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Sharpen was originally created by db40 [svn source here](https://source.db4o.com 1. Clone this repository 2. Install Java 7 and maven. Java 6 and 8 aren’t supported. 3. Run ‘mvn clean test’ to test -4. Run ‘mvn install ’ to generate .jar files in /sharpen.core/target +4. Run ‘mvn install ’ to generate .jar files in /src/target ### Running sharpen @@ -38,7 +38,7 @@ Sharpen’s command-line options don’t let you fully override all conversion o #### Creating external config class Your external configuration class must: -* inherit [Configuration](sharpen.core/src/sharpen/core/Configuration.java) class; +* inherit [Configuration](src/main/sharpen/core/Configuration.java) class; * must be publicly visible; * must have a public constructor; diff --git a/src/test/sharpen/ui/tests/AbstractConversionTestCase.java b/src/test/sharpen/ui/tests/AbstractConversionTestCase.java index 88d9af8..af6f1c5 100644 --- a/src/test/sharpen/ui/tests/AbstractConversionTestCase.java +++ b/src/test/sharpen/ui/tests/AbstractConversionTestCase.java @@ -37,7 +37,7 @@ public abstract class AbstractConversionTestCase { protected JavaProjectCmd _project; private String projectName="DPrj"; //To Run from MAVEN - protected String projecttempLocation = System.getProperty("user.dir") + "/sharpen.core/target/testcases"; + protected String projecttempLocation = System.getProperty("user.dir") + "/src/target/testcases"; //To Run From Eclipse GUI //protected String projecttempLocation = System.getProperty("user.dir") + "/sharpen.ui.tests/testcases"; @Before From e2c46ec23b85de7e465cd1e9dbea1d695590f9a7 Mon Sep 17 00:00:00 2001 From: ydanila Date: Wed, 11 Mar 2015 12:36:24 +0300 Subject: [PATCH 12/37] Now block comments keeps original indentation --- src/main/sharpen/core/CSharpBuilder.java | 79 ++++++++++++++----- .../sharpen/core/csharp/CSharpPrinter.java | 2 +- .../core/csharp/ast/CSBlockComment.java | 2 +- src/test/resources/comments/BodyBlock.cs.txt | 12 +-- ...nericAnonymousWithAdditionalMethods.cs.txt | 8 +- 5 files changed, 71 insertions(+), 32 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index f1dcc45..5b63844 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -154,30 +154,69 @@ public boolean visit(LineComment node) { @Override public boolean visit(BlockComment node) { - _compilationUnit.addComment(new CSBlockComment(node.getStartPosition(), getText(node.getStartPosition(), node + String originalIndentation = getIndentation(node.getStartPosition()); + _compilationUnit.addComment(new CSBlockComment(node.getStartPosition(), originalIndentation + getText(node.getStartPosition(), node .getLength()))); return false; - }; - - private String getText(int startPosition, int length) { - try { - ICompilationUnit cu = (ICompilationUnit) _ast.getJavaElement(); - if(cu != null){ - IBuffer buffer = cu.getBuffer(); - if(buffer != null){ - return buffer.getText(startPosition, length); - } - } + } - if(_content != null && !_content.isEmpty()){ - return _content.substring(startPosition, startPosition + length); - } + private String getIndentation(int position) { + try { + ICompilationUnit cu = (ICompilationUnit) _ast.getJavaElement(); + String content; + if(cu != null){ + IBuffer buffer = cu.getBuffer(); + if(buffer == null){ + return ""; + } + + content = buffer.getContents(); + } + else { + content = _content; + } + + if (content == null || content.isEmpty()) { + return ""; + } + + StringBuilder builder = new StringBuilder(); + + while(position > 0){ + char ch = content.charAt(--position); + if(ch == ' ' || ch == '\t'){ + builder.insert(0, ch); + continue; + } + + break; + } + + return builder.toString(); + } catch (JavaModelException e) { + throw new RuntimeException(e); + } + } - return ""; - } catch (JavaModelException e) { - throw new RuntimeException(e); - } - } + private String getText(int startPosition, int length) { + try { + ICompilationUnit cu = (ICompilationUnit) _ast.getJavaElement(); + if(cu != null){ + IBuffer buffer = cu.getBuffer(); + if(buffer != null){ + return buffer.getText(startPosition, length); + } + } + + if(_content != null && !_content.isEmpty()){ + return _content.substring(startPosition, startPosition + length); + } + + return ""; + } catch (JavaModelException e) { + throw new RuntimeException(e); + } + } public CSCompilationUnit compilationUnit() { return _compilationUnit; diff --git a/src/main/sharpen/core/csharp/CSharpPrinter.java b/src/main/sharpen/core/csharp/CSharpPrinter.java index da9da93..6e70615 100644 --- a/src/main/sharpen/core/csharp/CSharpPrinter.java +++ b/src/main/sharpen/core/csharp/CSharpPrinter.java @@ -446,7 +446,7 @@ public void visit(CSLineComment node) { @Override public void visit(CSBlockComment node) { for(String line : node.lines()){ - writeIndentedLine(line); + writeLine(line); } } diff --git a/src/main/sharpen/core/csharp/ast/CSBlockComment.java b/src/main/sharpen/core/csharp/ast/CSBlockComment.java index d01db64..0e43a5f 100644 --- a/src/main/sharpen/core/csharp/ast/CSBlockComment.java +++ b/src/main/sharpen/core/csharp/ast/CSBlockComment.java @@ -46,7 +46,7 @@ private String[] getLines(String text) { String[] lines = text.split("\\r?\\n"); for(int i = 0; i < lines.length; i++){ - lines[i] = lines[i].trim(); + lines[i] = lines[i]; } return lines; diff --git a/src/test/resources/comments/BodyBlock.cs.txt b/src/test/resources/comments/BodyBlock.cs.txt index aabcb3b..1ca333f 100644 --- a/src/test/resources/comments/BodyBlock.cs.txt +++ b/src/test/resources/comments/BodyBlock.cs.txt @@ -2,16 +2,16 @@ namespace comments { public class BodyBlock { - /* - * Block comment tabs indented - */ + /* + * Block comment tabs indented + */ public virtual void foo() { } - /* - * Block comment spaces indented - */ + /* + * Block comment spaces indented + */ public virtual void bar() { } diff --git a/src/test/resources/innerclasses/GenericAnonymousWithAdditionalMethods.cs.txt b/src/test/resources/innerclasses/GenericAnonymousWithAdditionalMethods.cs.txt index 709affd..92912f7 100644 --- a/src/test/resources/innerclasses/GenericAnonymousWithAdditionalMethods.cs.txt +++ b/src/test/resources/innerclasses/GenericAnonymousWithAdditionalMethods.cs.txt @@ -18,10 +18,10 @@ namespace innerclasses return this.result(target); } - /* - For some unknown reason in MappingsImpl#isDeclaringClassIgnoringExtends() declaringClassBinding believes it is non anonymous. - I can see, people don't like to be anonymous (at least most of the time). - */ + /* + For some unknown reason in MappingsImpl#isDeclaringClassIgnoringExtends() declaringClassBinding believes it is non anonymous. + I can see, people don't like to be anonymous (at least most of the time). + */ private int result(object target) { return 0; From 64ebfba8c4bdf1929de55058b59bd5d7255e106b Mon Sep 17 00:00:00 2001 From: ydanila Date: Thu, 12 Mar 2015 11:51:36 +0300 Subject: [PATCH 13/37] Fix for char autocasting --- src/main/sharpen/core/CSharpBuilder.java | 20 ++++++++++++++------ src/test/resources/autocasting/Char.cs.txt | 10 +++++++++- src/test/resources/autocasting/Char.java.txt | 10 +++++++++- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 5b63844..c8b3131 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -1790,6 +1790,7 @@ private void processMethodDeclaration(MethodDeclaration node) { } CSMethod method = new CSMethod(mappedMethodDeclarationName(node)); + ITypeBinding savedType = pushExpectedType(node.getReturnType2().resolveBinding()); method.returnType(mappedReturnType(node)); method.modifier(mapMethodModifier(node)); mapTypeParameters(node.typeParameters(), method); @@ -1811,6 +1812,7 @@ else if (method.name().equals("TearDown")) { } } } + popExpectedType(savedType); } private void cleanBaseSetupCalls (CSMethod method) { @@ -2443,7 +2445,7 @@ public boolean visit(SynchronizedStatement node) { } public boolean visit(ReturnStatement node) { - addStatement(new CSReturnStatement(node.getStartPosition(), mapExpression(node.getExpression()))); + addStatement(new CSReturnStatement(node.getStartPosition(), mapExpression(_currentExpectedType, node.getExpression()))); return false; } @@ -2452,11 +2454,17 @@ public boolean visit(NumberLiteral node) { String token = node.getToken(); CSExpression literal = new CSNumberLiteralExpression(token); - if (expectingType ("byte") && token.startsWith("-")) { + if (expectingType ("byte") && token.startsWith("-")) { literal = uncheckedCast ("byte",literal); } else if (token.startsWith("0x")) { - if (token.endsWith("l") || token.endsWith("L")) { + if (expectingType ("char")) { + if(token.startsWith("-")) { + unsupportedConstruct(node, "Negative number cannot be converted to char"); + return false; + } + } + else if (token.endsWith("l") || token.endsWith("L")) { literal = uncheckedCast("long", literal); } else { literal = uncheckedCast("int", literal); @@ -2475,7 +2483,7 @@ else if (token.startsWith("0x")) { return false; } - private CSUncheckedExpression uncheckedCast(String type, CSExpression expression) { + private CSUncheckedExpression uncheckedCast(String type, CSExpression expression) { return new CSUncheckedExpression(new CSCastExpression(new CSTypeReference(type), new CSParenthesizedExpression( expression))); } @@ -2726,7 +2734,7 @@ public boolean visit(SwitchStatement node) { openCaseBlock.addStatement(new CSGotoStatement (Integer.MIN_VALUE, "default")); } else { ITypeBinding stype = pushExpectedType (switchType); - CSExpression caseExpression = mapExpression(sc.getExpression()); + CSExpression caseExpression = mapExpression(switchType, sc.getExpression()); current.addExpression(caseExpression); popExpectedType(stype); if (openCaseBlock != null) @@ -2919,7 +2927,7 @@ public boolean visit(Assignment node) { } private CSExpression mapExpression(ITypeBinding expectedType, Expression expression) { - if (expectedType != null) + if (expectedType != null && expectedType != resolveWellKnownType("void")) return castIfNeeded(expectedType, expression.resolveTypeBinding(), mapExpression(expression)); else return mapExpression (expression); diff --git a/src/test/resources/autocasting/Char.cs.txt b/src/test/resources/autocasting/Char.cs.txt index 2dd0d06..be8e8d5 100644 --- a/src/test/resources/autocasting/Char.cs.txt +++ b/src/test/resources/autocasting/Char.cs.txt @@ -4,9 +4,17 @@ namespace autocasting { private char _ch; - private void test() + private char test() { this._ch = (char)1; + switch (this._ch) + { + case (char)0x0022: + { + return (char)0x0033; + } + } + return ' '; } } } \ No newline at end of file diff --git a/src/test/resources/autocasting/Char.java.txt b/src/test/resources/autocasting/Char.java.txt index ab473d4..aff7635 100644 --- a/src/test/resources/autocasting/Char.java.txt +++ b/src/test/resources/autocasting/Char.java.txt @@ -3,7 +3,15 @@ package autocasting; class CharAutocasting { private char _ch; - private void test() { + private char test() { this._ch = 1; + + switch (this._ch) + { + case 0x0022: + return 0x0033; + } + + return ' '; } } \ No newline at end of file From 07f0f12e07b40d9ebe15fb8b382f2dc43c6e847d Mon Sep 17 00:00:00 2001 From: ydanila Date: Thu, 12 Mar 2015 12:01:41 +0300 Subject: [PATCH 14/37] Autocasting for conditional expression --- src/main/sharpen/core/CSharpBuilder.java | 5 +++-- src/test/resources/autocasting/Char.cs.txt | 6 ++++++ src/test/resources/autocasting/Char.java.txt | 6 ++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index c8b3131..7e4d22f 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -2832,8 +2832,9 @@ public boolean visit(ParenthesizedExpression node) { } public boolean visit(ConditionalExpression node) { - pushExpression(new CSConditionalExpression(mapExpression(node.getExpression()), mapExpression(node - .getThenExpression()), mapExpression(node.getElseExpression()))); + pushExpression(new CSConditionalExpression(mapExpression(node.getExpression()), + mapExpression(_currentExpectedType, node.getThenExpression()), + mapExpression(_currentExpectedType, node.getElseExpression()))); return false; } diff --git a/src/test/resources/autocasting/Char.cs.txt b/src/test/resources/autocasting/Char.cs.txt index be8e8d5..7727e68 100644 --- a/src/test/resources/autocasting/Char.cs.txt +++ b/src/test/resources/autocasting/Char.cs.txt @@ -16,5 +16,11 @@ namespace autocasting } return ' '; } + + public virtual char ch(int index) + { + string str = "teststr"; + return index < str.Length ? str[index] : (char)0x0000; + } } } \ No newline at end of file diff --git a/src/test/resources/autocasting/Char.java.txt b/src/test/resources/autocasting/Char.java.txt index aff7635..adaf0f4 100644 --- a/src/test/resources/autocasting/Char.java.txt +++ b/src/test/resources/autocasting/Char.java.txt @@ -14,4 +14,10 @@ class CharAutocasting { return ' '; } + + public char ch(int index) + { + String str = "teststr"; + return index < str.length() ? str.charAt(index) : 0x0000; + } } \ No newline at end of file From 0f63199b5309458d4fddc31e5b3f23cc51106def Mon Sep 17 00:00:00 2001 From: ydanila Date: Thu, 12 Mar 2015 12:13:49 +0300 Subject: [PATCH 15/37] Unchecked casts type mapping --- src/main/sharpen/core/CSharpBuilder.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 7e4d22f..861a9ca 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -2455,7 +2455,7 @@ public boolean visit(NumberLiteral node) { CSExpression literal = new CSNumberLiteralExpression(token); if (expectingType ("byte") && token.startsWith("-")) { - literal = uncheckedCast ("byte",literal); + literal = uncheckedCast (mappedTypeName("byte"),literal); } else if (token.startsWith("0x")) { if (expectingType ("char")) { @@ -2465,9 +2465,9 @@ else if (token.startsWith("0x")) { } } else if (token.endsWith("l") || token.endsWith("L")) { - literal = uncheckedCast("long", literal); + literal = uncheckedCast(mappedTypeName("long"), literal); } else { - literal = uncheckedCast("int", literal); + literal = uncheckedCast(mappedTypeName("int"), literal); } } else if (token.startsWith("0") && token.indexOf('.') == -1 && Character.isDigit(token.charAt(token.length() - 1))) { @@ -2782,7 +2782,7 @@ public boolean visit(PrefixExpression node) { CSExpression expr; expr = new CSPrefixExpression(node.getOperator().toString(), mapExpression(node.getOperand())); if (expectingType ("byte") && node.getOperator() == PrefixExpression.Operator.MINUS) { - expr = uncheckedCast ("byte", expr); + expr = uncheckedCast (mappedTypeName("byte"), expr); } pushExpression(expr); return false; From 4977bdad5b75477686dab4ea3b419c5249254123 Mon Sep 17 00:00:00 2001 From: ydanila Date: Thu, 12 Mar 2015 17:35:30 +0300 Subject: [PATCH 16/37] Declaration expression autocasting --- src/main/sharpen/core/CSharpBuilder.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 861a9ca..9c682c7 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -2195,8 +2195,9 @@ public boolean visit(VariableDeclarationStatement node) { private CSVariableDeclaration createVariableDeclaration(VariableDeclarationFragment variable) { IVariableBinding binding = variable.resolveBinding(); - ITypeBinding saved = pushExpectedType(binding.getType()); - CSExpression initializer = mapExpression(variable.getInitializer()); + ITypeBinding expectedType = binding.getType(); + ITypeBinding saved = pushExpectedType(expectedType); + CSExpression initializer = mapExpression(expectedType, variable.getInitializer()); popExpectedType(saved); return createVariableDeclaration(binding, initializer); } @@ -2928,6 +2929,9 @@ public boolean visit(Assignment node) { } private CSExpression mapExpression(ITypeBinding expectedType, Expression expression) { + if (null == expression) + return null; + if (expectedType != null && expectedType != resolveWellKnownType("void")) return castIfNeeded(expectedType, expression.resolveTypeBinding(), mapExpression(expression)); else From fb4aa7f5c306c7cdd7f09ca5bbf07d79ae368fea Mon Sep 17 00:00:00 2001 From: ydanila Date: Fri, 13 Mar 2015 14:48:29 +0300 Subject: [PATCH 17/37] Nested class invocation fix --- src/main/sharpen/core/AbstractNestedClassBuilder.java | 6 ++++-- src/main/sharpen/core/CSharpBuilder.java | 7 ++++++- src/test/resources/innerclasses/NestedClass2.cs.txt | 3 +++ src/test/resources/innerclasses/NestedClass2.java.txt | 2 ++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/main/sharpen/core/AbstractNestedClassBuilder.java b/src/main/sharpen/core/AbstractNestedClassBuilder.java index 13eaf7d..914668d 100644 --- a/src/main/sharpen/core/AbstractNestedClassBuilder.java +++ b/src/main/sharpen/core/AbstractNestedClassBuilder.java @@ -32,7 +32,9 @@ */ public abstract class AbstractNestedClassBuilder extends CSharpBuilder { - private boolean _usesEnclosingMember; + public static final String ENCLOSING_FIELD = "_enclosing"; + + private boolean _usesEnclosingMember; public AbstractNestedClassBuilder(CSharpBuilder other) { super(other); @@ -145,7 +147,7 @@ private ITypeBinding getDeclaringClass(Name reference) { } protected CSField createEnclosingField() { - return CSharpCode.newPrivateReadonlyField("_enclosing", enclosingTypeReference()); + return CSharpCode.newPrivateReadonlyField(ENCLOSING_FIELD, enclosingTypeReference()); } private CSTypeReference enclosingTypeReference() { diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 9c682c7..917f591 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -2978,7 +2978,12 @@ public boolean visit(ClassInstanceCreation node) { } if (isNonStaticNestedTypeCreation(node)) { - expression.addArgument(new CSThisExpression()); + if(_currentType.name().equals(node.resolveTypeBinding().getName())){ + expression.addArgument(new CSMemberReferenceExpression(new CSThisExpression(), AbstractNestedClassBuilder.ENCLOSING_FIELD)); + } + else { + expression.addArgument(new CSThisExpression()); + } } mapArguments(expression, node.arguments()); diff --git a/src/test/resources/innerclasses/NestedClass2.cs.txt b/src/test/resources/innerclasses/NestedClass2.cs.txt index 95d947f..a9ba702 100644 --- a/src/test/resources/innerclasses/NestedClass2.cs.txt +++ b/src/test/resources/innerclasses/NestedClass2.cs.txt @@ -4,6 +4,8 @@ namespace innerclasses { public class Foo { + private innerclasses.NestedClass2.Foo _child; + public Foo(NestedClass2 _enclosing, int i) { this._enclosing = _enclosing; @@ -12,6 +14,7 @@ namespace innerclasses public virtual void foo() { this._enclosing.bar(); + this._child = new innerclasses.NestedClass2.Foo(this._enclosing, 1); } private readonly NestedClass2 _enclosing; diff --git a/src/test/resources/innerclasses/NestedClass2.java.txt b/src/test/resources/innerclasses/NestedClass2.java.txt index 894c78e..f0ce7ff 100644 --- a/src/test/resources/innerclasses/NestedClass2.java.txt +++ b/src/test/resources/innerclasses/NestedClass2.java.txt @@ -2,10 +2,12 @@ package innerclasses; public class NestedClass2 { public class Foo { + private Foo _child; public Foo(int i) { } public void foo() { bar(); + _child = new Foo(1); } } From 2aa0b790b171aa31c1e5b6aedff49cf1de139007 Mon Sep 17 00:00:00 2001 From: ydanila Date: Fri, 13 Mar 2015 18:44:46 +0300 Subject: [PATCH 18/37] Collection<> also is generic collection --- src/main/sharpen/core/CSharpBuilder.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 917f591..28a1e66 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -2954,7 +2954,8 @@ private CSExpression castIfNeeded(ITypeBinding expectedType, ITypeBinding actual } private boolean isGenericCollection (ITypeBinding t) { - return t.getName().startsWith("List<") || t.getName().startsWith("Set<"); + return t.getName().startsWith("List<") || t.getName().startsWith("Set<") + || t.getName().startsWith("Collection<"); } private boolean isSubclassOf (ITypeBinding t, ITypeBinding tbase) { From 6860fb264611a823a5a35cdfae266bcdf6787c9f Mon Sep 17 00:00:00 2001 From: ydanila Date: Sat, 14 Mar 2015 20:16:57 +0300 Subject: [PATCH 19/37] Do not add unchecked cast if cast already defined --- src/main/sharpen/core/CSharpBuilder.java | 11 +++++++++-- src/test/resources/autocasting/Hex.cs.txt | 8 ++++++++ src/test/resources/autocasting/Hex.java.txt | 7 +++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 28a1e66..5850e21 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -2455,8 +2455,11 @@ public boolean visit(NumberLiteral node) { String token = node.getToken(); CSExpression literal = new CSNumberLiteralExpression(token); - if (expectingType ("byte") && token.startsWith("-")) { - literal = uncheckedCast (mappedTypeName("byte"),literal); + if (hasCastExpression(node)) { + // if cast already defined - do nothing + } + else if (expectingType ("byte") && token.startsWith("-")) { + literal = uncheckedCast (mappedTypeName("byte"),literal); } else if (token.startsWith("0x")) { if (expectingType ("char")) { @@ -2489,6 +2492,10 @@ private CSUncheckedExpression uncheckedCast(String type, CSExpression expression expression))); } + private boolean hasCastExpression(NumberLiteral node) { + return (node.getParent() instanceof CastExpression); + } + public boolean visit(StringLiteral node) { String value = node.getLiteralValue(); if (value != null && value.length() == 0) { diff --git a/src/test/resources/autocasting/Hex.cs.txt b/src/test/resources/autocasting/Hex.cs.txt index 2a0a3ea..ebb8673 100644 --- a/src/test/resources/autocasting/Hex.cs.txt +++ b/src/test/resources/autocasting/Hex.cs.txt @@ -10,6 +10,14 @@ namespace autocasting withLong(unchecked((long)(0xabl))); } + public virtual void withCastDefined() + { + withInt((int)0xab); + withLong((int)0xab); + withLong((long)0xabL); + withLong((long)0xabL); + } + private void withLong(long l) { } diff --git a/src/test/resources/autocasting/Hex.java.txt b/src/test/resources/autocasting/Hex.java.txt index 544068f..55ee6f8 100644 --- a/src/test/resources/autocasting/Hex.java.txt +++ b/src/test/resources/autocasting/Hex.java.txt @@ -9,6 +9,13 @@ public class Hex { withLong(0xabl); } + public void withCastDefined() { + withInt((int)0xab); + withLong((int)0xab); + withLong((long)0xabL); + withLong((long)0xabL); + } + private void withLong(long l) { } From 1a327d937970f471d9a64b165412bc48806517a9 Mon Sep 17 00:00:00 2001 From: ydanila Date: Sun, 15 Mar 2015 10:09:58 +0300 Subject: [PATCH 20/37] Removed excessive casting like (short)(unchecked(short)) Replacing casting with unchecked casting if value out of range --- src/main/sharpen/core/CSharpBuilder.java | 65 +++++++++++++++++---- src/test/resources/autocasting/Hex.cs.txt | 6 ++ src/test/resources/autocasting/Hex.java.txt | 5 ++ 3 files changed, 65 insertions(+), 11 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 5850e21..bbab2f1 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -2456,10 +2456,13 @@ public boolean visit(NumberLiteral node) { CSExpression literal = new CSNumberLiteralExpression(token); if (hasCastExpression(node)) { - // if cast already defined - do nothing + ITypeBinding castTypeBinding = getCastType(node).resolveBinding(); + if(!isInRange(castTypeBinding, token)){ + literal = uncheckedCast (mappedTypeName(castTypeBinding.getName()), literal); + } } else if (expectingType ("byte") && token.startsWith("-")) { - literal = uncheckedCast (mappedTypeName("byte"),literal); + literal = uncheckedCast (mappedTypeName("byte"),literal); } else if (token.startsWith("0x")) { if (expectingType ("char")) { @@ -2487,15 +2490,29 @@ else if (token.endsWith("l") || token.endsWith("L")) { return false; } + private boolean hasCastExpression(NumberLiteral node) { + return (node.getParent() instanceof CastExpression); + } + + private Type getCastType(NumberLiteral node) { + return ((CastExpression)node.getParent()).getType(); + } + + private boolean isInRange(ITypeBinding typeBinding, String token) { + if(typeBinding.getQualifiedName().equals("short")){ + Long val = Long.decode(token); + // check that it matches C# range + return val >= -32768 && val <= 32767; + } + + return true; + } + private CSUncheckedExpression uncheckedCast(String type, CSExpression expression) { return new CSUncheckedExpression(new CSCastExpression(new CSTypeReference(type), new CSParenthesizedExpression( expression))); } - private boolean hasCastExpression(NumberLiteral node) { - return (node.getParent() instanceof CastExpression); - } - public boolean visit(StringLiteral node) { String value = node.getLiteralValue(); if (value != null && value.length() == 0) { @@ -2779,14 +2796,40 @@ public boolean visit(SwitchStatement node) { } public boolean visit(CastExpression node) { - pushExpression(new CSCastExpression(mappedTypeReference(node.getType()), mapExpression(node.getExpression()))); - // Make all byte casts unchecked - if (node.getType().resolveBinding().getName().equals("byte")) - pushExpression(new CSUncheckedExpression (popExpression())); + CSExpression expression = mapExpression(node.getExpression()); + if(isSameTypeCast(node, expression)) { + pushExpression(expression); + } + else { + pushExpression(new CSCastExpression(mappedTypeReference(node.getType()), expression)); + // Make all byte casts unchecked + if (node.getType().resolveBinding().getName().equals("byte")) + pushExpression(new CSUncheckedExpression (popExpression())); + } return false; } - public boolean visit(PrefixExpression node) { + private boolean isSameTypeCast(CastExpression node, CSExpression expression) { + CSExpression castExpression = expression; + if(expression instanceof CSUncheckedExpression){ + castExpression = ((CSUncheckedExpression)expression).expression(); + } + if (!(castExpression instanceof CSCastExpression)) { + return false; + } + return castTypeName((CSCastExpression)castExpression).equals(mappedTypeName(node.resolveTypeBinding())); + } + + private String castTypeName(CSCastExpression cast) { + CSTypeReferenceExpression expression = cast.type(); + if(expression instanceof CSTypeReference){ + return ((CSTypeReference)expression).typeName(); + } + + throw new UnsupportedOperationException(); + } + + public boolean visit(PrefixExpression node) { CSExpression expr; expr = new CSPrefixExpression(node.getOperator().toString(), mapExpression(node.getOperand())); if (expectingType ("byte") && node.getOperator() == PrefixExpression.Operator.MINUS) { diff --git a/src/test/resources/autocasting/Hex.cs.txt b/src/test/resources/autocasting/Hex.cs.txt index ebb8673..814000a 100644 --- a/src/test/resources/autocasting/Hex.cs.txt +++ b/src/test/resources/autocasting/Hex.cs.txt @@ -12,6 +12,8 @@ namespace autocasting public virtual void withCastDefined() { + withShort((short)0x00FF); + withShort(unchecked((short)(0xFF00))); withInt((int)0xab); withLong((int)0xab); withLong((long)0xabL); @@ -25,5 +27,9 @@ namespace autocasting private void withInt(int i) { } + + private void withShort(short i) + { + } } } \ No newline at end of file diff --git a/src/test/resources/autocasting/Hex.java.txt b/src/test/resources/autocasting/Hex.java.txt index 55ee6f8..ea6c28e 100644 --- a/src/test/resources/autocasting/Hex.java.txt +++ b/src/test/resources/autocasting/Hex.java.txt @@ -10,6 +10,8 @@ public class Hex { } public void withCastDefined() { + withShort((short)0x00FF); + withShort((short)0xFF00); withInt((int)0xab); withLong((int)0xab); withLong((long)0xabL); @@ -21,4 +23,7 @@ public class Hex { private void withInt(int i) { } + + private void withShort(short i) { + } } \ No newline at end of file From eac764058b05e22bc99de575c8d8cc05e53e8708 Mon Sep 17 00:00:00 2001 From: ydanila Date: Mon, 16 Mar 2015 12:45:49 +0300 Subject: [PATCH 21/37] Better support for wildcards conversion --- src/main/sharpen/core/CSharpBuilder.java | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index bbab2f1..bfbff64 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -4188,8 +4188,25 @@ private ITypeBinding javaLangClassBinding() { } private CSTypeReferenceExpression mappedWildcardTypeReference(ITypeBinding type) { - final ITypeBinding bound = type.getBound(); - return bound != null ? mappedTypeReference(bound) : OBJECT_TYPE_REFERENCE; + final ITypeBinding bound = type.getBound(); + if (bound == null) { + return OBJECT_TYPE_REFERENCE; + } + + CSTypeReferenceExpression mappedTypeReference = mappedTypeReference(bound); + + if(_currentMethod != null && _currentMethod instanceof CSMethod){ + CSMethod method = (CSMethod)_currentMethod; + if(method.typeParameters().size() > 0){ + for(CSTypeParameter param : method.typeParameters()){ + if(param.superClass().equals(mappedTypeReference)){ + return new CSTypeReference(param.name()); + } + } + } + } + + return mappedTypeReference; } private CSTypeReferenceExpression mappedArrayTypeReference(ITypeBinding type) { From cdaa78714b6f737c2d52c26b4a153f1da99d22e7 Mon Sep 17 00:00:00 2001 From: ydanila Date: Sun, 29 Mar 2015 17:15:57 +0300 Subject: [PATCH 22/37] Autocasting support for double? with test --- src/main/sharpen/core/CSharpBuilder.java | 25 ++++++++++---- src/test/resources/autocasting/Double.cs.txt | 21 ++++++++++++ .../resources/autocasting/Double.java.txt | 18 ++++++++++ .../sharpen/ui/tests/AutoCastingTestCase.java | 34 +++++++++++++------ 4 files changed, 81 insertions(+), 17 deletions(-) create mode 100644 src/test/resources/autocasting/Double.cs.txt create mode 100644 src/test/resources/autocasting/Double.java.txt diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index bfbff64..348c01a 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -2996,13 +2996,26 @@ private CSExpression castIfNeeded(ITypeBinding expectedType, ITypeBinding actual return new CSCastExpression(mappedTypeReference(expectedType), expression); ITypeBinding charType = resolveWellKnownType("char"); - if (expectedType != charType) - return expression; - if (actualType == expectedType) - return expression; - return new CSCastExpression(mappedTypeReference(expectedType), expression); + if (expectedType == charType) { + if (actualType == expectedType) + return expression; + + return new CSCastExpression(mappedTypeReference(expectedType), expression); + } + + CSTypeReferenceExpression mappedActualType = mappedTypeReference(actualType); + CSTypeReferenceExpression mappedExpectedType = mappedTypeReference(expectedType); + + if(mappedActualType instanceof CSTypeReference && mappedExpectedType instanceof CSTypeReference) { + if (((CSTypeReference)mappedExpectedType).typeName().equals("double") && + ((CSTypeReference)mappedActualType).typeName().equals("double?")) { + return new CSCastExpression(mappedTypeReference(expectedType), expression); + } + } + + return expression; } - + private boolean isGenericCollection (ITypeBinding t) { return t.getName().startsWith("List<") || t.getName().startsWith("Set<") || t.getName().startsWith("Collection<"); diff --git a/src/test/resources/autocasting/Double.cs.txt b/src/test/resources/autocasting/Double.cs.txt new file mode 100644 index 0000000..ad6347f --- /dev/null +++ b/src/test/resources/autocasting/Double.cs.txt @@ -0,0 +1,21 @@ +namespace autocasting +{ + internal class CharAutocasting + { + public virtual double dbl() + { + double? val = 110.00; + double? res = minus((double)val, 100.00); + if (res != null) + { + return (double)res; + } + return 0; + } + + private double minus(double arg1, double arg2) + { + return arg1 - arg2; + } + } +} \ No newline at end of file diff --git a/src/test/resources/autocasting/Double.java.txt b/src/test/resources/autocasting/Double.java.txt new file mode 100644 index 0000000..b6ec7fa --- /dev/null +++ b/src/test/resources/autocasting/Double.java.txt @@ -0,0 +1,18 @@ +package autocasting; + +class CharAutocasting { + + public double dbl(){ + Double val = 110.00; + Double res = minus(val, 100.00); + if(res != null){ + return res; + } + + return 0; + } + + private double minus(double arg1, double arg2){ + return arg1 - arg2; + } +} \ No newline at end of file diff --git a/src/test/sharpen/ui/tests/AutoCastingTestCase.java b/src/test/sharpen/ui/tests/AutoCastingTestCase.java index 594dfae..551f987 100644 --- a/src/test/sharpen/ui/tests/AutoCastingTestCase.java +++ b/src/test/sharpen/ui/tests/AutoCastingTestCase.java @@ -19,21 +19,33 @@ with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* Copyright (C) 2004 - 2006 Versant Inc. http://www.db4o.com */ - -package sharpen.ui.tests; +/* Copyright (C) 2004 - 2006 Versant Inc. http://www.db4o.com */ + +package sharpen.ui.tests; import org.junit.Test; - -public class AutoCastingTestCase extends AbstractConversionTestCase { - +import sharpen.core.Configuration; + +public class AutoCastingTestCase extends AbstractConversionTestCase { + + @Override + protected Configuration getConfiguration() { + final Configuration config = super.getConfiguration(); + config.mapType("java.lang.Double", "double?"); + return config; + } + @Test - public void testChar() throws Throwable { - runResourceTestCase("autocasting/Char"); - } + public void testChar() throws Throwable { + runResourceTestCase("autocasting/Char"); + } @Test public void testHex() throws Throwable { runResourceTestCase("autocasting/Hex"); } - -} + + @Test + public void testDouble() throws Throwable { + runResourceTestCase("autocasting/Double"); + } +} From 782d5ec9e7a24c26d577e00770721f818d5bf4a4 Mon Sep 17 00:00:00 2001 From: ydanila Date: Sun, 29 Mar 2015 18:12:38 +0300 Subject: [PATCH 23/37] Better support for double? casting to double --- src/main/sharpen/core/CSharpBuilder.java | 34 ++++++++++++++----- src/test/resources/autocasting/Double.cs.txt | 12 +++++-- .../resources/autocasting/Double.java.txt | 11 ++++-- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 348c01a..85f916e 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -2690,7 +2690,7 @@ public boolean visit(EnhancedForStatement node) { public boolean visit(final ForStatement node) { consumeContinueLabel(new Function() { public CSBlock apply() { - ArrayList initializers = new ArrayList (); + ArrayList initializers = new ArrayList(); for (Object i : node.initializers()) { initializers.add(mapExpression((Expression) i)); } @@ -2846,8 +2846,12 @@ public boolean visit(PostfixExpression node) { public boolean visit(InfixExpression node) { + ITypeBinding expressionExpectedType = node.resolveTypeBinding(); + ITypeBinding prevExpectedType = pushExpectedType(expressionExpectedType); + CSExpression left = mapExpression(node.getLeftOperand()); CSExpression right = mapExpression(node.getRightOperand()); + popExpectedType(prevExpectedType); String type = node.getLeftOperand().resolveTypeBinding().getQualifiedName(); if (node.getOperator() == InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED) { if (type.equals ("byte")) { @@ -2891,7 +2895,7 @@ public boolean visit(ConditionalExpression node) { public boolean visit(InstanceofExpression node) { pushExpression(new CSInfixExpression("is", mapExpression(node.getLeftOperand()), mappedTypeReference(node - .getRightOperand().resolveBinding()))); + .getRightOperand().resolveBinding()))); return false; } @@ -3003,12 +3007,17 @@ private CSExpression castIfNeeded(ITypeBinding expectedType, ITypeBinding actual return new CSCastExpression(mappedTypeReference(expectedType), expression); } + return castNullableIfRequired(expectedType, actualType, expression); + } + + private CSExpression castNullableIfRequired(ITypeBinding expectedType, ITypeBinding actualType, CSExpression expression) { CSTypeReferenceExpression mappedActualType = mappedTypeReference(actualType); CSTypeReferenceExpression mappedExpectedType = mappedTypeReference(expectedType); if(mappedActualType instanceof CSTypeReference && mappedExpectedType instanceof CSTypeReference) { if (((CSTypeReference)mappedExpectedType).typeName().equals("double") && ((CSTypeReference)mappedActualType).typeName().equals("double?")) { + return new CSCastExpression(mappedTypeReference(expectedType), expression); } } @@ -3670,24 +3679,31 @@ public boolean visit(SimpleName node) { String ident = mapVariableName (identifier (node)); IBinding b = node.resolveBinding(); IVariableBinding vb = b instanceof IVariableBinding ? (IVariableBinding) b : null; + CSReferenceExpression resultExpression = null; if (vb != null) { ITypeBinding cls = vb.getDeclaringClass(); if (cls != null) { if (isStaticImport(vb, _ast.imports())) { - pushExpression(new CSMemberReferenceExpression(mappedTypeReference(cls), ident)); - return false; + resultExpression = new CSMemberReferenceExpression(mappedTypeReference(cls), ident); } else if (cls.isEnum() && ident.indexOf('.') == -1 && vb.isEnumConstant()){ - pushExpression(new CSMemberReferenceExpression(mappedTypeReference(cls), ident)); - return false; + resultExpression = new CSMemberReferenceExpression(mappedTypeReference(cls), ident); } else if (_configuration.separateInterfaceConstants() && cls.isInterface() && ident.indexOf('.') == -1) { - pushExpression(new CSMemberReferenceExpression(mappedAuxillaryTypeReference(cls), ident)); - return false; + resultExpression = new CSMemberReferenceExpression(mappedAuxillaryTypeReference(cls), ident); } } } - pushExpression(new CSReferenceExpression(ident)); + if(resultExpression == null) { + resultExpression = new CSReferenceExpression(ident); + } + + /// because Java makes autocasting i.e Double -> double, only one way to support nullables in C#, + /// to cast nullable to expected type immediately + + ITypeBinding actualType = node.resolveTypeBinding(); + + pushExpression(castNullableIfRequired(_currentExpectedType, actualType, resultExpression)); } return false; } diff --git a/src/test/resources/autocasting/Double.cs.txt b/src/test/resources/autocasting/Double.cs.txt index ad6347f..72e25c9 100644 --- a/src/test/resources/autocasting/Double.cs.txt +++ b/src/test/resources/autocasting/Double.cs.txt @@ -5,17 +5,23 @@ namespace autocasting public virtual double dbl() { double? val = 110.00; - double? res = minus((double)val, 100.00); + double? res = minus((double)val, (double)val / 2); if (res != null) { - return (double)res; + return (double)res + 5; } return 0; } private double minus(double arg1, double arg2) { - return arg1 - arg2; + double? result = arg1 - arg2; + double test = (double)result + 4; + if (test < 0) + { + return 0; + } + return (double)(double)result; } } } \ No newline at end of file diff --git a/src/test/resources/autocasting/Double.java.txt b/src/test/resources/autocasting/Double.java.txt index b6ec7fa..bdf9aaa 100644 --- a/src/test/resources/autocasting/Double.java.txt +++ b/src/test/resources/autocasting/Double.java.txt @@ -4,15 +4,20 @@ class CharAutocasting { public double dbl(){ Double val = 110.00; - Double res = minus(val, 100.00); + Double res = minus(val, val / 2); if(res != null){ - return res; + return res + 5; } return 0; } private double minus(double arg1, double arg2){ - return arg1 - arg2; + Double result = arg1 - arg2; + double test = result + 4; + if(test < 0) + return 0; + + return result; } } \ No newline at end of file From 0d8dd09948ffc5c9909e0ebc871388ad692e8465 Mon Sep 17 00:00:00 2001 From: ydanila Date: Mon, 30 Mar 2015 09:47:15 +0300 Subject: [PATCH 24/37] Fixed duplication of casting expression --- src/main/sharpen/core/CSharpBuilder.java | 20 ++++++++++++++------ src/test/resources/autocasting/Double.cs.txt | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 85f916e..b686b9b 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -2797,7 +2797,7 @@ public boolean visit(SwitchStatement node) { public boolean visit(CastExpression node) { CSExpression expression = mapExpression(node.getExpression()); - if(isSameTypeCast(node, expression)) { + if(isSameTypeCast(expression, mappedTypeName(node.resolveTypeBinding()))) { pushExpression(expression); } else { @@ -2809,7 +2809,7 @@ public boolean visit(CastExpression node) { return false; } - private boolean isSameTypeCast(CastExpression node, CSExpression expression) { + private boolean isSameTypeCast(CSExpression expression, String expectedCSType) { CSExpression castExpression = expression; if(expression instanceof CSUncheckedExpression){ castExpression = ((CSUncheckedExpression)expression).expression(); @@ -2817,7 +2817,7 @@ private boolean isSameTypeCast(CastExpression node, CSExpression expression) { if (!(castExpression instanceof CSCastExpression)) { return false; } - return castTypeName((CSCastExpression)castExpression).equals(mappedTypeName(node.resolveTypeBinding())); + return castTypeName((CSCastExpression)castExpression).equals(expectedCSType); } private String castTypeName(CSCastExpression cast) { @@ -3007,10 +3007,14 @@ private CSExpression castIfNeeded(ITypeBinding expectedType, ITypeBinding actual return new CSCastExpression(mappedTypeReference(expectedType), expression); } - return castNullableIfRequired(expectedType, actualType, expression); + return castNullableIfNeeded(expectedType, actualType, expression); } - private CSExpression castNullableIfRequired(ITypeBinding expectedType, ITypeBinding actualType, CSExpression expression) { + private CSExpression castNullableIfNeeded(ITypeBinding expectedType, ITypeBinding actualType, CSExpression expression) { + if(expectedType == null){ + return expression; + } + CSTypeReferenceExpression mappedActualType = mappedTypeReference(actualType); CSTypeReferenceExpression mappedExpectedType = mappedTypeReference(expectedType); @@ -3018,6 +3022,10 @@ private CSExpression castNullableIfRequired(ITypeBinding expectedType, ITypeBind if (((CSTypeReference)mappedExpectedType).typeName().equals("double") && ((CSTypeReference)mappedActualType).typeName().equals("double?")) { + if(isSameTypeCast(expression, mappedTypeName(expectedType))) { + return expression; + } + return new CSCastExpression(mappedTypeReference(expectedType), expression); } } @@ -3703,7 +3711,7 @@ else if (_configuration.separateInterfaceConstants() && cls.isInterface() && ide ITypeBinding actualType = node.resolveTypeBinding(); - pushExpression(castNullableIfRequired(_currentExpectedType, actualType, resultExpression)); + pushExpression(castNullableIfNeeded(_currentExpectedType, actualType, resultExpression)); } return false; } diff --git a/src/test/resources/autocasting/Double.cs.txt b/src/test/resources/autocasting/Double.cs.txt index 72e25c9..c3c0945 100644 --- a/src/test/resources/autocasting/Double.cs.txt +++ b/src/test/resources/autocasting/Double.cs.txt @@ -21,7 +21,7 @@ namespace autocasting { return 0; } - return (double)(double)result; + return (double)result; } } } \ No newline at end of file From f8ae480e84ceaad3852e147c753f73871ffeab8c Mon Sep 17 00:00:00 2001 From: ydanila Date: Mon, 30 Mar 2015 10:43:16 +0300 Subject: [PATCH 25/37] Fixed side-effect with adding excessive usings --- src/main/sharpen/core/CSharpBuilder.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index b686b9b..ad1c09e 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -3015,6 +3015,10 @@ private CSExpression castNullableIfNeeded(ITypeBinding expectedType, ITypeBindin return expression; } + if(!isNullableType(actualType)) { + return expression; + } + CSTypeReferenceExpression mappedActualType = mappedTypeReference(actualType); CSTypeReferenceExpression mappedExpectedType = mappedTypeReference(expectedType); @@ -3033,6 +3037,11 @@ private CSExpression castNullableIfNeeded(ITypeBinding expectedType, ITypeBindin return expression; } + private boolean isNullableType(ITypeBinding type) { + return type != null && + (type.getQualifiedName().equals("java.lang.Double")); + } + private boolean isGenericCollection (ITypeBinding t) { return t.getName().startsWith("List<") || t.getName().startsWith("Set<") || t.getName().startsWith("Collection<"); From 84b1c5902fbdd6ddcd4ff648753f20f441ee9e99 Mon Sep 17 00:00:00 2001 From: ydanila Date: Mon, 30 Mar 2015 10:57:12 +0300 Subject: [PATCH 26/37] Refactoring --- src/main/sharpen/core/CSharpBuilder.java | 31 +++++++++++++++--------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index ad1c09e..d7babf2 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -3007,10 +3007,10 @@ private CSExpression castIfNeeded(ITypeBinding expectedType, ITypeBinding actual return new CSCastExpression(mappedTypeReference(expectedType), expression); } - return castNullableIfNeeded(expectedType, actualType, expression); + return castToValueTypeIfNeeded(expectedType, actualType, expression); } - private CSExpression castNullableIfNeeded(ITypeBinding expectedType, ITypeBinding actualType, CSExpression expression) { + private CSExpression castToValueTypeIfNeeded(ITypeBinding expectedType, ITypeBinding actualType, CSExpression expression) { if(expectedType == null){ return expression; } @@ -3022,16 +3022,12 @@ private CSExpression castNullableIfNeeded(ITypeBinding expectedType, ITypeBindin CSTypeReferenceExpression mappedActualType = mappedTypeReference(actualType); CSTypeReferenceExpression mappedExpectedType = mappedTypeReference(expectedType); - if(mappedActualType instanceof CSTypeReference && mappedExpectedType instanceof CSTypeReference) { - if (((CSTypeReference)mappedExpectedType).typeName().equals("double") && - ((CSTypeReference)mappedActualType).typeName().equals("double?")) { - - if(isSameTypeCast(expression, mappedTypeName(expectedType))) { - return expression; - } + if(isSameTypeCast(expression, mappedTypeName(expectedType))) { + return expression; + } - return new CSCastExpression(mappedTypeReference(expectedType), expression); - } + if(isNullableFor(mappedActualType, mappedExpectedType)){ + return new CSCastExpression(mappedTypeReference(expectedType), expression); } return expression; @@ -3042,6 +3038,17 @@ private boolean isNullableType(ITypeBinding type) { (type.getQualifiedName().equals("java.lang.Double")); } + private boolean isNullableFor(CSTypeReferenceExpression nullableType, CSTypeReferenceExpression valueType) { + if (!(nullableType instanceof CSTypeReference) || !(valueType instanceof CSTypeReference)) { + return false; + } + + String nullableTypeName = ((CSTypeReference)nullableType).typeName(); + String valueTypeName = ((CSTypeReference)valueType).typeName(); + + return nullableTypeName.equals(valueTypeName + "?"); + } + private boolean isGenericCollection (ITypeBinding t) { return t.getName().startsWith("List<") || t.getName().startsWith("Set<") || t.getName().startsWith("Collection<"); @@ -3720,7 +3727,7 @@ else if (_configuration.separateInterfaceConstants() && cls.isInterface() && ide ITypeBinding actualType = node.resolveTypeBinding(); - pushExpression(castNullableIfNeeded(_currentExpectedType, actualType, resultExpression)); + pushExpression(castToValueTypeIfNeeded(_currentExpectedType, actualType, resultExpression)); } return false; } From 0b2a85d9a1ce223db2a3f9968f15a785ee790019 Mon Sep 17 00:00:00 2001 From: ydanila Date: Mon, 30 Mar 2015 11:50:55 +0300 Subject: [PATCH 27/37] Support for other nullable types with tests --- src/main/sharpen/core/CSharpBuilder.java | 6 ++++- src/test/resources/autocasting/Boolean.cs.txt | 26 ++++++++++++++++++ .../resources/autocasting/Boolean.java.txt | 22 +++++++++++++++ src/test/resources/autocasting/Float.cs.txt | 27 +++++++++++++++++++ src/test/resources/autocasting/Float.java.txt | 23 ++++++++++++++++ src/test/resources/autocasting/Integer.cs.txt | 27 +++++++++++++++++++ .../resources/autocasting/Integer.java.txt | 23 ++++++++++++++++ src/test/resources/autocasting/Long.cs.txt | 27 +++++++++++++++++++ src/test/resources/autocasting/Long.java.txt | 23 ++++++++++++++++ .../sharpen/ui/tests/AutoCastingTestCase.java | 25 +++++++++++++++++ 10 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 src/test/resources/autocasting/Boolean.cs.txt create mode 100644 src/test/resources/autocasting/Boolean.java.txt create mode 100644 src/test/resources/autocasting/Float.cs.txt create mode 100644 src/test/resources/autocasting/Float.java.txt create mode 100644 src/test/resources/autocasting/Integer.cs.txt create mode 100644 src/test/resources/autocasting/Integer.java.txt create mode 100644 src/test/resources/autocasting/Long.cs.txt create mode 100644 src/test/resources/autocasting/Long.java.txt diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index d7babf2..5660878 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -3035,7 +3035,11 @@ private CSExpression castToValueTypeIfNeeded(ITypeBinding expectedType, ITypeBin private boolean isNullableType(ITypeBinding type) { return type != null && - (type.getQualifiedName().equals("java.lang.Double")); + (type.getQualifiedName().equals("java.lang.Double") || + type.getQualifiedName().equals("java.lang.Integer") || + type.getQualifiedName().equals("java.lang.Long") || + type.getQualifiedName().equals("java.lang.Float") || + type.getQualifiedName().equals("java.lang.Boolean")); } private boolean isNullableFor(CSTypeReferenceExpression nullableType, CSTypeReferenceExpression valueType) { diff --git a/src/test/resources/autocasting/Boolean.cs.txt b/src/test/resources/autocasting/Boolean.cs.txt new file mode 100644 index 0000000..0406950 --- /dev/null +++ b/src/test/resources/autocasting/Boolean.cs.txt @@ -0,0 +1,26 @@ +namespace autocasting +{ + internal class CharAutocasting + { + public virtual bool booleanval(int x) + { + bool? val = true; + bool? res = resolve((bool)val, (bool)val || (x == 2)); + if ((bool)res != null) + { + return (bool)res || (x == 3); + } + return false; + } + + private bool resolve(bool arg1, bool? arg2) + { + bool? result = arg1 && (bool)arg2; + if ((bool)result) + { + return true; + } + return (bool)result; + } + } +} \ No newline at end of file diff --git a/src/test/resources/autocasting/Boolean.java.txt b/src/test/resources/autocasting/Boolean.java.txt new file mode 100644 index 0000000..0ef8bdb --- /dev/null +++ b/src/test/resources/autocasting/Boolean.java.txt @@ -0,0 +1,22 @@ +package autocasting; + +class CharAutocasting { + + public boolean booleanval(int x){ + Boolean val = true; + Boolean res = resolve(val, val || (x == 2)); + if(res != null){ + return res || (x == 3); + } + + return false; + } + + private boolean resolve(boolean arg1, Boolean arg2){ + Boolean result = arg1 && arg2; + if(result) + return true; + + return result; + } +} \ No newline at end of file diff --git a/src/test/resources/autocasting/Float.cs.txt b/src/test/resources/autocasting/Float.cs.txt new file mode 100644 index 0000000..23aedb1 --- /dev/null +++ b/src/test/resources/autocasting/Float.cs.txt @@ -0,0 +1,27 @@ +namespace autocasting +{ + internal class CharAutocasting + { + public virtual float floatval() + { + float? val = 110.0F; + float? res = minus((float)val, (float)val / 2); + if (res != null) + { + return (float)res + 5; + } + return 0; + } + + private float minus(float arg1, float arg2) + { + float? result = arg1 - arg2; + float test = (float)result + 4; + if (test < 0) + { + return 0; + } + return (float)result; + } + } +} \ No newline at end of file diff --git a/src/test/resources/autocasting/Float.java.txt b/src/test/resources/autocasting/Float.java.txt new file mode 100644 index 0000000..b6e2579 --- /dev/null +++ b/src/test/resources/autocasting/Float.java.txt @@ -0,0 +1,23 @@ +package autocasting; + +class CharAutocasting { + + public float floatval(){ + Float val = 110.0F; + Float res = minus(val, val / 2); + if(res != null){ + return res + 5; + } + + return 0; + } + + private float minus(float arg1, float arg2){ + Float result = arg1 - arg2; + float test = result + 4; + if(test < 0) + return 0; + + return result; + } +} \ No newline at end of file diff --git a/src/test/resources/autocasting/Integer.cs.txt b/src/test/resources/autocasting/Integer.cs.txt new file mode 100644 index 0000000..7a63248 --- /dev/null +++ b/src/test/resources/autocasting/Integer.cs.txt @@ -0,0 +1,27 @@ +namespace autocasting +{ + internal class CharAutocasting + { + public virtual int integer() + { + int? val = 110; + int? res = minus((int)val, (int)val / 2); + if (res != null) + { + return (int)res + 5; + } + return 0; + } + + private int minus(int arg1, int arg2) + { + int? result = arg1 - arg2; + int test = (int)result + 4; + if (test < 0) + { + return 0; + } + return (int)result; + } + } +} \ No newline at end of file diff --git a/src/test/resources/autocasting/Integer.java.txt b/src/test/resources/autocasting/Integer.java.txt new file mode 100644 index 0000000..0db2693 --- /dev/null +++ b/src/test/resources/autocasting/Integer.java.txt @@ -0,0 +1,23 @@ +package autocasting; + +class CharAutocasting { + + public int integer(){ + Integer val = 110; + Integer res = minus(val, val / 2); + if(res != null){ + return res + 5; + } + + return 0; + } + + private int minus(int arg1, int arg2){ + Integer result = arg1 - arg2; + int test = result + 4; + if(test < 0) + return 0; + + return result; + } +} \ No newline at end of file diff --git a/src/test/resources/autocasting/Long.cs.txt b/src/test/resources/autocasting/Long.cs.txt new file mode 100644 index 0000000..4580663 --- /dev/null +++ b/src/test/resources/autocasting/Long.cs.txt @@ -0,0 +1,27 @@ +namespace autocasting +{ + internal class CharAutocasting + { + public virtual long longval() + { + long? val = 110L; + long? res = minus((long)val, (long)val / 2); + if (res != null) + { + return (long)res + 5; + } + return 0; + } + + private long minus(long arg1, long arg2) + { + long? result = arg1 - arg2; + long test = (long)result + 4; + if (test < 0) + { + return 0; + } + return (long)result; + } + } +} \ No newline at end of file diff --git a/src/test/resources/autocasting/Long.java.txt b/src/test/resources/autocasting/Long.java.txt new file mode 100644 index 0000000..712ca38 --- /dev/null +++ b/src/test/resources/autocasting/Long.java.txt @@ -0,0 +1,23 @@ +package autocasting; + +class CharAutocasting { + + public long longval(){ + Long val = 110L; + Long res = minus(val, val / 2); + if(res != null){ + return res + 5; + } + + return 0; + } + + private long minus(long arg1, long arg2){ + Long result = arg1 - arg2; + long test = result + 4; + if(test < 0) + return 0; + + return result; + } +} \ No newline at end of file diff --git a/src/test/sharpen/ui/tests/AutoCastingTestCase.java b/src/test/sharpen/ui/tests/AutoCastingTestCase.java index 551f987..9b6d7ec 100644 --- a/src/test/sharpen/ui/tests/AutoCastingTestCase.java +++ b/src/test/sharpen/ui/tests/AutoCastingTestCase.java @@ -31,6 +31,11 @@ public class AutoCastingTestCase extends AbstractConversionTestCase { protected Configuration getConfiguration() { final Configuration config = super.getConfiguration(); config.mapType("java.lang.Double", "double?"); + config.mapType("java.lang.Integer", "int?"); + config.mapType("java.lang.Long", "long?"); + config.mapType("java.lang.Float", "float?"); + config.mapType("java.lang.Boolean", "bool?"); + config.mapType("java.util.Date", "System.DateTime?"); return config; } @@ -48,4 +53,24 @@ public void testHex() throws Throwable { public void testDouble() throws Throwable { runResourceTestCase("autocasting/Double"); } + + @Test + public void testInteger() throws Throwable { + runResourceTestCase("autocasting/Integer"); + } + + @Test + public void testLong() throws Throwable { + runResourceTestCase("autocasting/Long"); + } + + @Test + public void testFloat() throws Throwable { + runResourceTestCase("autocasting/Float"); + } + + @Test + public void testBoolean() throws Throwable { + runResourceTestCase("autocasting/Boolean"); + } } From fdb91c55f16d24bb35f1a9bcea539271793a9175 Mon Sep 17 00:00:00 2001 From: ydanila Date: Mon, 30 Mar 2015 14:36:18 +0300 Subject: [PATCH 28/37] Better support for value types casting including constructor invocation --- src/main/sharpen/core/CSharpBuilder.java | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 5660878..931b3d4 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -2140,13 +2140,13 @@ private CSExpression getLockTarget(BodyDeclaration node) { } public boolean visit(ConstructorInvocation node) { - addChainedConstructorInvocation(new CSThisExpression(), node.arguments()); + addChainedConstructorInvocation(new CSThisExpression(), node.resolveConstructorBinding().getParameterTypes(), node.arguments()); return false; } - private void addChainedConstructorInvocation(CSExpression target, List arguments) { + private void addChainedConstructorInvocation(CSExpression target, ITypeBinding[] constructorArgTypes, List arguments) { CSConstructorInvocationExpression cie = new CSConstructorInvocationExpression(target); - mapArguments(cie, arguments); + mapArguments(cie, constructorArgTypes, arguments); ((CSConstructor) _currentMethod).chainedConstructorInvocation(cie); } @@ -2154,7 +2154,7 @@ public boolean visit(SuperConstructorInvocation node) { if (null != node.getExpression()) { notImplemented(node); } - addChainedConstructorInvocation(new CSBaseExpression(), node.arguments()); + addChainedConstructorInvocation(new CSBaseExpression(), node.resolveConstructorBinding().getTypeArguments(), node.arguments()); return false; } @@ -2939,7 +2939,7 @@ public boolean visit(EnumConstantDeclaration node) { } } - mapArguments(initializer, node.arguments()); + mapArguments(initializer, new ITypeBinding[0], node.arguments()); CSField field = new CSField(fieldName(node), typeName, visibility, initializer); field.addModifier(CSFieldModifier.Static); @@ -3087,7 +3087,8 @@ public boolean visit(ClassInstanceCreation node) { } } - mapArguments(expression, node.arguments()); + ITypeBinding[] constructorArgsTypes = node.resolveConstructorBinding().getParameterTypes(); + mapArguments(expression, constructorArgsTypes, node.arguments()); pushExpression(expression); return false; } @@ -3189,7 +3190,7 @@ public boolean visit(SuperMethodInvocation node) { } CSMethodInvocationExpression mie = new CSMethodInvocationExpression(target); - mapArguments(mie, node.arguments()); + mapArguments(mie, node.resolveMethodBinding().getParameterTypes(), node.arguments()); pushExpression(mie); return false; } @@ -3596,7 +3597,7 @@ private void processMappedMethodInvocation(MethodInvocation node, IMethodBinding mie.addArgument(expression); } } - mapArguments(mie, arguments); + mapArguments(mie, node.resolveMethodBinding().getParameterTypes(), arguments); adjustJUnitArguments(mie, node); pushExpression(mie); } @@ -3658,9 +3659,9 @@ private boolean isMappingToStaticMember(String name) { return -1 != name.indexOf('.'); } - protected void mapArguments(CSMethodInvocationExpression mie, List arguments) { - for (Object arg : arguments) { - addArgument(mie, (Expression) arg, null); + protected void mapArguments(CSMethodInvocationExpression mie, ITypeBinding[] constructorArgTypes, List arguments) { + for (int i = 0; i < arguments.size(); i++) { + addArgument(mie, (Expression) arguments.get(i), i < constructorArgTypes.length ? constructorArgTypes[i] : null); } } From fd53e9ff4288c3ab1ad7cd53f56466ee3d6dca16 Mon Sep 17 00:00:00 2001 From: ydanila Date: Mon, 30 Mar 2015 18:11:48 +0300 Subject: [PATCH 29/37] Support for safe casting of some value types --- src/main/sharpen/core/CSharpBuilder.java | 91 ++++++++++++++++++++---- 1 file changed, 77 insertions(+), 14 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 931b3d4..b3d302d 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -3015,34 +3015,68 @@ private CSExpression castToValueTypeIfNeeded(ITypeBinding expectedType, ITypeBin return expression; } - if(!isNullableType(actualType)) { - return expression; - } + if (isPrimitiveType(actualType) || isNullableType(actualType)) { - CSTypeReferenceExpression mappedActualType = mappedTypeReference(actualType); - CSTypeReferenceExpression mappedExpectedType = mappedTypeReference(expectedType); + CSTypeReferenceExpression mappedActualType = mappedTypeReference(actualType); + CSTypeReferenceExpression mappedExpectedType = mappedTypeReference(expectedType); - if(isSameTypeCast(expression, mappedTypeName(expectedType))) { - return expression; - } + if (isSameTypeCast(expression, mappedTypeName(expectedType))) { + return expression; + } - if(isNullableFor(mappedActualType, mappedExpectedType)){ - return new CSCastExpression(mappedTypeReference(expectedType), expression); + if (isNullableFor(mappedActualType, mappedExpectedType)) { + return new CSCastExpression(mappedExpectedType, expression); + } + + if(canBeCastedTo(mappedActualType, mappedExpectedType)) { + + if(expression instanceof CSCastExpression){ + return new CSCastExpression(mappedExpectedType, ((CSCastExpression)expression).expression()); + } + + return new CSCastExpression(mappedExpectedType, expression); + } + + if (mappedActualType instanceof CSTypeReference && mappedExpectedType instanceof CSTypeReference) { + String actualTypeName = ((CSTypeReference) mappedActualType).typeName(); + String expectedTypeName = ((CSTypeReference) mappedExpectedType).typeName(); + if(actualTypeName.endsWith("?")) { + String valueType = actualTypeName.substring(0, actualTypeName.length() - 1); + if (canBeCastedTo(valueType, expectedTypeName)) { + + if(expression instanceof CSCastExpression){ + return new CSCastExpression(mappedExpectedType, ((CSCastExpression)expression).expression()); + } + + return new CSCastExpression(mappedExpectedType, expression); + } + } + } } return expression; } + private boolean isPrimitiveType(ITypeBinding type) { + return type != null && + (type.getQualifiedName().equals("double") || + type.getQualifiedName().equals("integer") || + type.getQualifiedName().equals("long") || + type.getQualifiedName().equals("float") || + type.getQualifiedName().equals("boolean")); + } + private boolean isNullableType(ITypeBinding type) { return type != null && (type.getQualifiedName().equals("java.lang.Double") || - type.getQualifiedName().equals("java.lang.Integer") || - type.getQualifiedName().equals("java.lang.Long") || - type.getQualifiedName().equals("java.lang.Float") || - type.getQualifiedName().equals("java.lang.Boolean")); + type.getQualifiedName().equals("java.lang.Integer") || + type.getQualifiedName().equals("java.lang.Long") || + type.getQualifiedName().equals("java.lang.Float") || + type.getQualifiedName().equals("java.lang.Boolean")); } private boolean isNullableFor(CSTypeReferenceExpression nullableType, CSTypeReferenceExpression valueType) { + if (!(nullableType instanceof CSTypeReference) || !(valueType instanceof CSTypeReference)) { return false; } @@ -3053,6 +3087,35 @@ private boolean isNullableFor(CSTypeReferenceExpression nullableType, CSTypeRefe return nullableTypeName.equals(valueTypeName + "?"); } + private boolean canBeCastedTo(CSTypeReferenceExpression actualType, CSTypeReferenceExpression expectedType) { + + if (!(actualType instanceof CSTypeReference) || !(expectedType instanceof CSTypeReference)) { + return false; + } + + String actualTypeName = ((CSTypeReference)actualType).typeName(); + String expectedTypeName = ((CSTypeReference)expectedType).typeName(); + + return canBeCastedTo(actualTypeName, expectedTypeName); + } + + private boolean canBeCastedTo(String actualTypeName, String expectedTypeName) { + + if(actualTypeName.equals("float?")){ + return expectedTypeName.equals("double"); + } + + if(actualTypeName.equals("double")){ + return expectedTypeName.equals("long"); + } + + if(actualTypeName.equals("int")){ + return expectedTypeName.equals("long"); + } + + return false; + } + private boolean isGenericCollection (ITypeBinding t) { return t.getName().startsWith("List<") || t.getName().startsWith("Set<") || t.getName().startsWith("Collection<"); From 129fadb225fc4739f943bdcb563344f9428b2c0a Mon Sep 17 00:00:00 2001 From: ydanila Date: Mon, 30 Mar 2015 19:23:36 +0300 Subject: [PATCH 30/37] Support for nullable autocasting to value type --- src/main/sharpen/core/CSharpBuilder.java | 104 ++++++++++++----------- 1 file changed, 56 insertions(+), 48 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index b3d302d..f3cd0a5 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -2797,10 +2797,18 @@ public boolean visit(SwitchStatement node) { public boolean visit(CastExpression node) { CSExpression expression = mapExpression(node.getExpression()); - if(isSameTypeCast(expression, mappedTypeName(node.resolveTypeBinding()))) { + ITypeBinding actualType = node.resolveTypeBinding(); + String mappedActualTypeName = mappedTypeName(actualType); + if(isSameTypeCast(expression, mappedActualTypeName)) { pushExpression(expression); } - else { + else if(_currentExpectedType != null && + isValueTypeClass(actualType) && + mappedTypeName(_currentExpectedType).equals(valueTypeName(mappedActualTypeName))){ + // replaces cast to nullable value type by cast to value type + pushExpression(new CSCastExpression(mappedTypeReference(_currentExpectedType), expression)); + } + else { pushExpression(new CSCastExpression(mappedTypeReference(node.getType()), expression)); // Make all byte casts unchecked if (node.getType().resolveBinding().getName().equals("byte")) @@ -2809,7 +2817,15 @@ public boolean visit(CastExpression node) { return false; } - private boolean isSameTypeCast(CSExpression expression, String expectedCSType) { + private String valueTypeName(String csTypeName) { + if(csTypeName.endsWith("?")) { + return csTypeName.substring(0, csTypeName.length() - 1); + } + + return csTypeName; + } + + private boolean isSameTypeCast(CSExpression expression, String expectedCSType) { CSExpression castExpression = expression; if(expression instanceof CSUncheckedExpression){ castExpression = ((CSUncheckedExpression)expression).expression(); @@ -2888,8 +2904,8 @@ public boolean visit(ParenthesizedExpression node) { public boolean visit(ConditionalExpression node) { pushExpression(new CSConditionalExpression(mapExpression(node.getExpression()), - mapExpression(_currentExpectedType, node.getThenExpression()), - mapExpression(_currentExpectedType, node.getElseExpression()))); + mapExpression(_currentExpectedType, node.getThenExpression()), + mapExpression(_currentExpectedType, node.getElseExpression()))); return false; } @@ -3015,48 +3031,50 @@ private CSExpression castToValueTypeIfNeeded(ITypeBinding expectedType, ITypeBin return expression; } - if (isPrimitiveType(actualType) || isNullableType(actualType)) { + if (isPrimitiveType(actualType) || isValueTypeClass(actualType)) { - CSTypeReferenceExpression mappedActualType = mappedTypeReference(actualType); - CSTypeReferenceExpression mappedExpectedType = mappedTypeReference(expectedType); + CSTypeReferenceExpression mappedActualTypeReference = mappedTypeReference(actualType); + CSTypeReferenceExpression mappedExpectedTypeReference = mappedTypeReference(expectedType); if (isSameTypeCast(expression, mappedTypeName(expectedType))) { return expression; } - if (isNullableFor(mappedActualType, mappedExpectedType)) { - return new CSCastExpression(mappedExpectedType, expression); + if (!(mappedActualTypeReference instanceof CSTypeReference) || !(mappedExpectedTypeReference instanceof CSTypeReference)) { + return expression; } - if(canBeCastedTo(mappedActualType, mappedExpectedType)) { + CSTypeReference mappedActualType = (CSTypeReference)mappedActualTypeReference; + CSTypeReference mappedExpectedType = (CSTypeReference)mappedExpectedTypeReference; - if(expression instanceof CSCastExpression){ - return new CSCastExpression(mappedExpectedType, ((CSCastExpression)expression).expression()); - } + if (isNullableFor(mappedActualType, mappedExpectedType) || + canBeCastedTo(mappedActualType, mappedExpectedType)) { - return new CSCastExpression(mappedExpectedType, expression); + return applyCast(expression, mappedExpectedType); } - if (mappedActualType instanceof CSTypeReference && mappedExpectedType instanceof CSTypeReference) { - String actualTypeName = ((CSTypeReference) mappedActualType).typeName(); - String expectedTypeName = ((CSTypeReference) mappedExpectedType).typeName(); - if(actualTypeName.endsWith("?")) { - String valueType = actualTypeName.substring(0, actualTypeName.length() - 1); - if (canBeCastedTo(valueType, expectedTypeName)) { + if (isNullableValueType(mappedActualType)) { + String actualTypeName = mappedActualType.typeName(); + String actualValueTypeName = actualTypeName.substring(0, actualTypeName.length() - 1); + if (canBeCastedTo(actualValueTypeName, mappedExpectedType.typeName())) { - if(expression instanceof CSCastExpression){ - return new CSCastExpression(mappedExpectedType, ((CSCastExpression)expression).expression()); - } - - return new CSCastExpression(mappedExpectedType, expression); - } - } - } + return applyCast(expression, mappedExpectedType); + } + } } return expression; } + private CSExpression applyCast(CSExpression expression, CSTypeReference mappedExpectedType) { + + if (expression instanceof CSCastExpression) { + return new CSCastExpression(mappedExpectedType, ((CSCastExpression) expression).expression()); + } + + return new CSCastExpression(mappedExpectedType, expression); + } + private boolean isPrimitiveType(ITypeBinding type) { return type != null && (type.getQualifiedName().equals("double") || @@ -3066,7 +3084,11 @@ private boolean isPrimitiveType(ITypeBinding type) { type.getQualifiedName().equals("boolean")); } - private boolean isNullableType(ITypeBinding type) { + private boolean isNullableValueType(CSTypeReference type) { + return type.typeName().endsWith("?"); + } + + private boolean isValueTypeClass(ITypeBinding type) { return type != null && (type.getQualifiedName().equals("java.lang.Double") || type.getQualifiedName().equals("java.lang.Integer") || @@ -3075,28 +3097,14 @@ private boolean isNullableType(ITypeBinding type) { type.getQualifiedName().equals("java.lang.Boolean")); } - private boolean isNullableFor(CSTypeReferenceExpression nullableType, CSTypeReferenceExpression valueType) { - - if (!(nullableType instanceof CSTypeReference) || !(valueType instanceof CSTypeReference)) { - return false; - } + private boolean isNullableFor(CSTypeReference nullableType, CSTypeReference valueType) { - String nullableTypeName = ((CSTypeReference)nullableType).typeName(); - String valueTypeName = ((CSTypeReference)valueType).typeName(); - - return nullableTypeName.equals(valueTypeName + "?"); + return isNullableValueType(nullableType) && valueTypeName(nullableType.typeName()).equals(valueType.typeName()); } - private boolean canBeCastedTo(CSTypeReferenceExpression actualType, CSTypeReferenceExpression expectedType) { - - if (!(actualType instanceof CSTypeReference) || !(expectedType instanceof CSTypeReference)) { - return false; - } - - String actualTypeName = ((CSTypeReference)actualType).typeName(); - String expectedTypeName = ((CSTypeReference)expectedType).typeName(); + private boolean canBeCastedTo(CSTypeReference actualType, CSTypeReference expectedType) { - return canBeCastedTo(actualTypeName, expectedTypeName); + return canBeCastedTo(actualType.typeName(), expectedType.typeName()); } private boolean canBeCastedTo(String actualTypeName, String expectedTypeName) { From 58bb4c068f89363e3cbbf858fe9f3001d9bd6083 Mon Sep 17 00:00:00 2001 From: ydanila Date: Tue, 31 Mar 2015 10:08:13 +0300 Subject: [PATCH 31/37] Tests for constructor invocation --- src/test/resources/autocasting/Boolean.cs.txt | 13 +++++++++++-- src/test/resources/autocasting/Boolean.java.txt | 11 +++++++++-- src/test/resources/autocasting/Double.cs.txt | 13 +++++++++++-- src/test/resources/autocasting/Double.java.txt | 11 +++++++++-- src/test/resources/autocasting/Float.cs.txt | 13 +++++++++++-- src/test/resources/autocasting/Float.java.txt | 11 +++++++++-- src/test/resources/autocasting/Integer.cs.txt | 13 +++++++++++-- src/test/resources/autocasting/Integer.java.txt | 11 +++++++++-- src/test/resources/autocasting/Long.cs.txt | 13 +++++++++++-- src/test/resources/autocasting/Long.java.txt | 11 +++++++++-- 10 files changed, 100 insertions(+), 20 deletions(-) diff --git a/src/test/resources/autocasting/Boolean.cs.txt b/src/test/resources/autocasting/Boolean.cs.txt index 0406950..2e041b5 100644 --- a/src/test/resources/autocasting/Boolean.cs.txt +++ b/src/test/resources/autocasting/Boolean.cs.txt @@ -1,10 +1,17 @@ namespace autocasting { - internal class CharAutocasting + internal class Autocasting { + private bool _b; + + private Autocasting(bool b) + { + _b = b; + } + public virtual bool booleanval(int x) { - bool? val = true; + bool? val = true && _b; bool? res = resolve((bool)val, (bool)val || (x == 2)); if ((bool)res != null) { @@ -20,6 +27,8 @@ namespace autocasting { return true; } + autocasting.Autocasting obj = new autocasting.Autocasting((bool)result); + result = obj.booleanval(10); return (bool)result; } } diff --git a/src/test/resources/autocasting/Boolean.java.txt b/src/test/resources/autocasting/Boolean.java.txt index 0ef8bdb..a16b416 100644 --- a/src/test/resources/autocasting/Boolean.java.txt +++ b/src/test/resources/autocasting/Boolean.java.txt @@ -1,9 +1,14 @@ package autocasting; -class CharAutocasting { +class Autocasting { + + private boolean _b; + private Autocasting(boolean b){ + _b = b; + } public boolean booleanval(int x){ - Boolean val = true; + Boolean val = true && _b; Boolean res = resolve(val, val || (x == 2)); if(res != null){ return res || (x == 3); @@ -17,6 +22,8 @@ class CharAutocasting { if(result) return true; + Autocasting obj = new Autocasting(result); + result = obj.booleanval(10); return result; } } \ No newline at end of file diff --git a/src/test/resources/autocasting/Double.cs.txt b/src/test/resources/autocasting/Double.cs.txt index c3c0945..ce5ea97 100644 --- a/src/test/resources/autocasting/Double.cs.txt +++ b/src/test/resources/autocasting/Double.cs.txt @@ -1,10 +1,17 @@ namespace autocasting { - internal class CharAutocasting + internal class Autocasting { + private double _d; + + private Autocasting(double d) + { + _d = d; + } + public virtual double dbl() { - double? val = 110.00; + double? val = 110.00 + _d; double? res = minus((double)val, (double)val / 2); if (res != null) { @@ -21,6 +28,8 @@ namespace autocasting { return 0; } + autocasting.Autocasting obj = new autocasting.Autocasting((double)result); + result = obj.dbl(); return (double)result; } } diff --git a/src/test/resources/autocasting/Double.java.txt b/src/test/resources/autocasting/Double.java.txt index bdf9aaa..b77c471 100644 --- a/src/test/resources/autocasting/Double.java.txt +++ b/src/test/resources/autocasting/Double.java.txt @@ -1,9 +1,14 @@ package autocasting; -class CharAutocasting { +class Autocasting { + + private double _d; + private Autocasting(double d){ + _d = d; + } public double dbl(){ - Double val = 110.00; + Double val = 110.00 + _d; Double res = minus(val, val / 2); if(res != null){ return res + 5; @@ -18,6 +23,8 @@ class CharAutocasting { if(test < 0) return 0; + Autocasting obj = new Autocasting(result); + result = obj.dbl(); return result; } } \ No newline at end of file diff --git a/src/test/resources/autocasting/Float.cs.txt b/src/test/resources/autocasting/Float.cs.txt index 23aedb1..891335c 100644 --- a/src/test/resources/autocasting/Float.cs.txt +++ b/src/test/resources/autocasting/Float.cs.txt @@ -1,10 +1,17 @@ namespace autocasting { - internal class CharAutocasting + internal class Autocasting { + private float _f; + + private Autocasting(float f) + { + _f = f; + } + public virtual float floatval() { - float? val = 110.0F; + float? val = 110.0F + _f; float? res = minus((float)val, (float)val / 2); if (res != null) { @@ -21,6 +28,8 @@ namespace autocasting { return 0; } + autocasting.Autocasting obj = new autocasting.Autocasting((float)result); + result = obj.floatval(); return (float)result; } } diff --git a/src/test/resources/autocasting/Float.java.txt b/src/test/resources/autocasting/Float.java.txt index b6e2579..d215eb0 100644 --- a/src/test/resources/autocasting/Float.java.txt +++ b/src/test/resources/autocasting/Float.java.txt @@ -1,9 +1,14 @@ package autocasting; -class CharAutocasting { +class Autocasting { + + private float _f; + private Autocasting(float f){ + _f = f; + } public float floatval(){ - Float val = 110.0F; + Float val = 110.0F + _f; Float res = minus(val, val / 2); if(res != null){ return res + 5; @@ -18,6 +23,8 @@ class CharAutocasting { if(test < 0) return 0; + Autocasting obj = new Autocasting(result); + result = obj.floatval(); return result; } } \ No newline at end of file diff --git a/src/test/resources/autocasting/Integer.cs.txt b/src/test/resources/autocasting/Integer.cs.txt index 7a63248..a4dd0cc 100644 --- a/src/test/resources/autocasting/Integer.cs.txt +++ b/src/test/resources/autocasting/Integer.cs.txt @@ -1,10 +1,17 @@ namespace autocasting { - internal class CharAutocasting + internal class Autocasting { + private int _i; + + private Autocasting(int i) + { + _i = i; + } + public virtual int integer() { - int? val = 110; + int? val = 110 + _i; int? res = minus((int)val, (int)val / 2); if (res != null) { @@ -21,6 +28,8 @@ namespace autocasting { return 0; } + autocasting.Autocasting obj = new autocasting.Autocasting((int)result); + result = obj.integer(); return (int)result; } } diff --git a/src/test/resources/autocasting/Integer.java.txt b/src/test/resources/autocasting/Integer.java.txt index 0db2693..296e2e4 100644 --- a/src/test/resources/autocasting/Integer.java.txt +++ b/src/test/resources/autocasting/Integer.java.txt @@ -1,9 +1,14 @@ package autocasting; -class CharAutocasting { +class Autocasting { + + private int _i; + private Autocasting(int i){ + _i = i; + } public int integer(){ - Integer val = 110; + Integer val = 110 + _i; Integer res = minus(val, val / 2); if(res != null){ return res + 5; @@ -18,6 +23,8 @@ class CharAutocasting { if(test < 0) return 0; + Autocasting obj = new Autocasting(result); + result = obj.integer(); return result; } } \ No newline at end of file diff --git a/src/test/resources/autocasting/Long.cs.txt b/src/test/resources/autocasting/Long.cs.txt index 4580663..a0b49d9 100644 --- a/src/test/resources/autocasting/Long.cs.txt +++ b/src/test/resources/autocasting/Long.cs.txt @@ -1,10 +1,17 @@ namespace autocasting { - internal class CharAutocasting + internal class Autocasting { + private long _l; + + private Autocasting(long l) + { + _l = l; + } + public virtual long longval() { - long? val = 110L; + long? val = 110L + _l; long? res = minus((long)val, (long)val / 2); if (res != null) { @@ -21,6 +28,8 @@ namespace autocasting { return 0; } + autocasting.Autocasting obj = new autocasting.Autocasting((long)result); + result = obj.longval(); return (long)result; } } diff --git a/src/test/resources/autocasting/Long.java.txt b/src/test/resources/autocasting/Long.java.txt index 712ca38..f5911a7 100644 --- a/src/test/resources/autocasting/Long.java.txt +++ b/src/test/resources/autocasting/Long.java.txt @@ -1,9 +1,14 @@ package autocasting; -class CharAutocasting { +class Autocasting { + + private long _l; + private Autocasting(long l){ + _l = l; + } public long longval(){ - Long val = 110L; + Long val = 110L + _l; Long res = minus(val, val / 2); if(res != null){ return res + 5; @@ -18,6 +23,8 @@ class CharAutocasting { if(test < 0) return 0; + Autocasting obj = new Autocasting(result); + result = obj.longval(); return result; } } \ No newline at end of file From 9b21999494068ecdb3300cbf4da5c596274bf045 Mon Sep 17 00:00:00 2001 From: ydanila Date: Tue, 31 Mar 2015 10:31:52 +0300 Subject: [PATCH 32/37] Tests for safe casts and safe casts replacements --- src/main/sharpen/core/CSharpBuilder.java | 16 ++++++---------- src/test/resources/autocasting/Float.cs.txt | 7 ++++--- src/test/resources/autocasting/Float.java.txt | 6 +++--- src/test/resources/autocasting/Integer.java.txt | 4 ++-- src/test/resources/autocasting/Long.cs.txt | 7 ++++--- src/test/resources/autocasting/Long.java.txt | 7 ++++--- 6 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index f3cd0a5..ef930c1 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -3048,7 +3048,7 @@ private CSExpression castToValueTypeIfNeeded(ITypeBinding expectedType, ITypeBin CSTypeReference mappedExpectedType = (CSTypeReference)mappedExpectedTypeReference; if (isNullableFor(mappedActualType, mappedExpectedType) || - canBeCastedTo(mappedActualType, mappedExpectedType)) { + canBeSafeCastedTo(mappedActualType, mappedExpectedType)) { return applyCast(expression, mappedExpectedType); } @@ -3056,7 +3056,7 @@ private CSExpression castToValueTypeIfNeeded(ITypeBinding expectedType, ITypeBin if (isNullableValueType(mappedActualType)) { String actualTypeName = mappedActualType.typeName(); String actualValueTypeName = actualTypeName.substring(0, actualTypeName.length() - 1); - if (canBeCastedTo(actualValueTypeName, mappedExpectedType.typeName())) { + if (canBeSafeCastedTo(actualValueTypeName, mappedExpectedType.typeName())) { return applyCast(expression, mappedExpectedType); } @@ -3102,22 +3102,18 @@ private boolean isNullableFor(CSTypeReference nullableType, CSTypeReference valu return isNullableValueType(nullableType) && valueTypeName(nullableType.typeName()).equals(valueType.typeName()); } - private boolean canBeCastedTo(CSTypeReference actualType, CSTypeReference expectedType) { + private boolean canBeSafeCastedTo(CSTypeReference actualType, CSTypeReference expectedType) { - return canBeCastedTo(actualType.typeName(), expectedType.typeName()); + return canBeSafeCastedTo(actualType.typeName(), expectedType.typeName()); } - private boolean canBeCastedTo(String actualTypeName, String expectedTypeName) { + private boolean canBeSafeCastedTo(String actualTypeName, String expectedTypeName) { if(actualTypeName.equals("float?")){ return expectedTypeName.equals("double"); } - if(actualTypeName.equals("double")){ - return expectedTypeName.equals("long"); - } - - if(actualTypeName.equals("int")){ + if(actualTypeName.equals("int?")){ return expectedTypeName.equals("long"); } diff --git a/src/test/resources/autocasting/Float.cs.txt b/src/test/resources/autocasting/Float.cs.txt index 891335c..0ea9e01 100644 --- a/src/test/resources/autocasting/Float.cs.txt +++ b/src/test/resources/autocasting/Float.cs.txt @@ -4,9 +4,9 @@ namespace autocasting { private float _f; - private Autocasting(float f) + private Autocasting(float f, double d) { - _f = f; + _f = f + (float)d; } public virtual float floatval() @@ -28,7 +28,8 @@ namespace autocasting { return 0; } - autocasting.Autocasting obj = new autocasting.Autocasting((float)result); + autocasting.Autocasting obj = new autocasting.Autocasting((float)result, (double) + result); result = obj.floatval(); return (float)result; } diff --git a/src/test/resources/autocasting/Float.java.txt b/src/test/resources/autocasting/Float.java.txt index d215eb0..bf665ba 100644 --- a/src/test/resources/autocasting/Float.java.txt +++ b/src/test/resources/autocasting/Float.java.txt @@ -3,8 +3,8 @@ package autocasting; class Autocasting { private float _f; - private Autocasting(float f){ - _f = f; + private Autocasting(float f, double d){ + _f = f + (float)d; } public float floatval(){ @@ -23,7 +23,7 @@ class Autocasting { if(test < 0) return 0; - Autocasting obj = new Autocasting(result); + Autocasting obj = new Autocasting(result, result); result = obj.floatval(); return result; } diff --git a/src/test/resources/autocasting/Integer.java.txt b/src/test/resources/autocasting/Integer.java.txt index 296e2e4..d823558 100644 --- a/src/test/resources/autocasting/Integer.java.txt +++ b/src/test/resources/autocasting/Integer.java.txt @@ -3,7 +3,7 @@ package autocasting; class Autocasting { private int _i; - private Autocasting(int i){ + private Autocasting(int i, int i2){ _i = i; } @@ -23,7 +23,7 @@ class Autocasting { if(test < 0) return 0; - Autocasting obj = new Autocasting(result); + Autocasting obj = new Autocasting(result, (Integer)test); result = obj.integer(); return result; } diff --git a/src/test/resources/autocasting/Long.cs.txt b/src/test/resources/autocasting/Long.cs.txt index a0b49d9..53c5cc7 100644 --- a/src/test/resources/autocasting/Long.cs.txt +++ b/src/test/resources/autocasting/Long.cs.txt @@ -4,9 +4,9 @@ namespace autocasting { private long _l; - private Autocasting(long l) + private Autocasting(long l, long l2) { - _l = l; + _l = l + l2; } public virtual long longval() @@ -28,7 +28,8 @@ namespace autocasting { return 0; } - autocasting.Autocasting obj = new autocasting.Autocasting((long)result); + int? i = 10; + autocasting.Autocasting obj = new autocasting.Autocasting((long)result, (long)i); result = obj.longval(); return (long)result; } diff --git a/src/test/resources/autocasting/Long.java.txt b/src/test/resources/autocasting/Long.java.txt index f5911a7..1da37b6 100644 --- a/src/test/resources/autocasting/Long.java.txt +++ b/src/test/resources/autocasting/Long.java.txt @@ -3,8 +3,8 @@ package autocasting; class Autocasting { private long _l; - private Autocasting(long l){ - _l = l; + private Autocasting(long l, long l2){ + _l = l + l2; } public long longval(){ @@ -23,7 +23,8 @@ class Autocasting { if(test < 0) return 0; - Autocasting obj = new Autocasting(result); + Integer i = 10; + Autocasting obj = new Autocasting(result, i); result = obj.longval(); return result; } From 08a8a8615a8aed3a1d285d66b25ec8c12829a512 Mon Sep 17 00:00:00 2001 From: ydanila Date: Tue, 31 Mar 2015 12:01:21 +0300 Subject: [PATCH 33/37] Support for unchecked cast long -> int with test --- src/main/sharpen/core/CSharpBuilder.java | 59 +++++++++++-------- src/test/resources/autocasting/Integer.cs.txt | 8 ++- .../resources/autocasting/Integer.java.txt | 4 +- 3 files changed, 44 insertions(+), 27 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index ef930c1..2388533 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -2455,8 +2455,8 @@ public boolean visit(NumberLiteral node) { String token = node.getToken(); CSExpression literal = new CSNumberLiteralExpression(token); - if (hasCastExpression(node)) { - ITypeBinding castTypeBinding = getCastType(node).resolveBinding(); + if (hasParentCastExpression(node)) { + ITypeBinding castTypeBinding = getParentCastType(node).resolveBinding(); if(!isInRange(castTypeBinding, token)){ literal = uncheckedCast (mappedTypeName(castTypeBinding.getName()), literal); } @@ -2490,11 +2490,11 @@ else if (token.endsWith("l") || token.endsWith("L")) { return false; } - private boolean hasCastExpression(NumberLiteral node) { + private boolean hasParentCastExpression(Expression node) { return (node.getParent() instanceof CastExpression); } - private Type getCastType(NumberLiteral node) { + private Type getParentCastType(Expression node) { return ((CastExpression)node.getParent()).getType(); } @@ -3003,12 +3003,17 @@ private CSExpression mapExpression(ITypeBinding expectedType, Expression express return null; if (expectedType != null && expectedType != resolveWellKnownType("void")) - return castIfNeeded(expectedType, expression.resolveTypeBinding(), mapExpression(expression)); + return castIfNeeded(expectedType, expression); else return mapExpression (expression); } - private CSExpression castIfNeeded(ITypeBinding expectedType, ITypeBinding actualType, CSExpression expression) { + private CSExpression castIfNeeded(ITypeBinding expectedType, Expression node) { + ITypeBinding actualType = node.resolveTypeBinding(); + ITypeBinding saved = pushExpectedType(expectedType); + CSExpression expression = mapExpression(node); + popExpectedType(saved); + if (!_configuration.mapIteratorToEnumerator() && expectedType.getName().startsWith("Iterable<") && isGenericCollection (actualType)) { return new CSMethodInvocationExpression (new CSMemberReferenceExpression (expression, "AsIterable")); } @@ -3023,14 +3028,16 @@ private CSExpression castIfNeeded(ITypeBinding expectedType, ITypeBinding actual return new CSCastExpression(mappedTypeReference(expectedType), expression); } - return castToValueTypeIfNeeded(expectedType, actualType, expression); + return castToValueTypeIfNeeded(node, expectedType, expression); } - private CSExpression castToValueTypeIfNeeded(ITypeBinding expectedType, ITypeBinding actualType, CSExpression expression) { + private CSExpression castToValueTypeIfNeeded(Expression node, ITypeBinding expectedType, CSExpression expression) { if(expectedType == null){ return expression; } + ITypeBinding actualType = node.resolveTypeBinding(); + if (isPrimitiveType(actualType) || isValueTypeClass(actualType)) { CSTypeReferenceExpression mappedActualTypeReference = mappedTypeReference(actualType); @@ -3048,19 +3055,15 @@ private CSExpression castToValueTypeIfNeeded(ITypeBinding expectedType, ITypeBin CSTypeReference mappedExpectedType = (CSTypeReference)mappedExpectedTypeReference; if (isNullableFor(mappedActualType, mappedExpectedType) || - canBeSafeCastedTo(mappedActualType, mappedExpectedType)) { + canBeCastedTo(mappedActualType, mappedExpectedType) || + canBeCastedTo(valueTypeName(mappedActualType.typeName()), mappedExpectedType.typeName())) { return applyCast(expression, mappedExpectedType); } - if (isNullableValueType(mappedActualType)) { - String actualTypeName = mappedActualType.typeName(); - String actualValueTypeName = actualTypeName.substring(0, actualTypeName.length() - 1); - if (canBeSafeCastedTo(actualValueTypeName, mappedExpectedType.typeName())) { - - return applyCast(expression, mappedExpectedType); - } - } + if(!hasParentCastExpression(node) && canBeUncheckedCastedTo(mappedActualType, mappedExpectedType)){ + return uncheckedCast(mappedExpectedType.typeName(), expression); + } } return expression; @@ -3102,12 +3105,12 @@ private boolean isNullableFor(CSTypeReference nullableType, CSTypeReference valu return isNullableValueType(nullableType) && valueTypeName(nullableType.typeName()).equals(valueType.typeName()); } - private boolean canBeSafeCastedTo(CSTypeReference actualType, CSTypeReference expectedType) { + private boolean canBeCastedTo(CSTypeReference actualType, CSTypeReference expectedType) { - return canBeSafeCastedTo(actualType.typeName(), expectedType.typeName()); + return canBeCastedTo(actualType.typeName(), expectedType.typeName()); } - private boolean canBeSafeCastedTo(String actualTypeName, String expectedTypeName) { + private boolean canBeCastedTo(String actualTypeName, String expectedTypeName) { if(actualTypeName.equals("float?")){ return expectedTypeName.equals("double"); @@ -3120,6 +3123,18 @@ private boolean canBeSafeCastedTo(String actualTypeName, String expectedTypeName return false; } + private boolean canBeUncheckedCastedTo(CSTypeReference actualType, CSTypeReference expectedType) { + + String actualTypeName = actualType.typeName(); + String expectedTypeName = expectedType.typeName(); + + if(actualTypeName.equals("long")){ + return expectedTypeName.equals("int"); + } + + return false; + } + private boolean isGenericCollection (ITypeBinding t) { return t.getName().startsWith("List<") || t.getName().startsWith("Set<") || t.getName().startsWith("Collection<"); @@ -3797,9 +3812,7 @@ else if (_configuration.separateInterfaceConstants() && cls.isInterface() && ide /// because Java makes autocasting i.e Double -> double, only one way to support nullables in C#, /// to cast nullable to expected type immediately - ITypeBinding actualType = node.resolveTypeBinding(); - - pushExpression(castToValueTypeIfNeeded(_currentExpectedType, actualType, resultExpression)); + pushExpression(castToValueTypeIfNeeded(node, _currentExpectedType, resultExpression)); } return false; } diff --git a/src/test/resources/autocasting/Integer.cs.txt b/src/test/resources/autocasting/Integer.cs.txt index a4dd0cc..29a2f24 100644 --- a/src/test/resources/autocasting/Integer.cs.txt +++ b/src/test/resources/autocasting/Integer.cs.txt @@ -4,7 +4,7 @@ namespace autocasting { private int _i; - private Autocasting(int i) + private Autocasting(int i, int i2) { _i = i; } @@ -17,7 +17,9 @@ namespace autocasting { return (int)res + 5; } - return 0; + long l = 100L; + _i += unchecked((int)(l)); + return _i; } private int minus(int arg1, int arg2) @@ -28,7 +30,7 @@ namespace autocasting { return 0; } - autocasting.Autocasting obj = new autocasting.Autocasting((int)result); + autocasting.Autocasting obj = new autocasting.Autocasting((int)result, (int)test); result = obj.integer(); return (int)result; } diff --git a/src/test/resources/autocasting/Integer.java.txt b/src/test/resources/autocasting/Integer.java.txt index d823558..33d09bb 100644 --- a/src/test/resources/autocasting/Integer.java.txt +++ b/src/test/resources/autocasting/Integer.java.txt @@ -14,7 +14,9 @@ class Autocasting { return res + 5; } - return 0; + long l = 100L; + _i += l; + return _i; } private int minus(int arg1, int arg2){ From c818e877b81885b2242e5284e789ef9791a82e5e Mon Sep 17 00:00:00 2001 From: ydanila Date: Tue, 31 Mar 2015 14:57:13 +0300 Subject: [PATCH 34/37] Fox for nullable boolean support --- src/main/sharpen/core/CSharpBuilder.java | 17 ++++++++++++++--- src/test/resources/autocasting/Boolean.cs.txt | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 2388533..0ad824e 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -2863,10 +2863,21 @@ public boolean visit(PostfixExpression node) { public boolean visit(InfixExpression node) { ITypeBinding expressionExpectedType = node.resolveTypeBinding(); - ITypeBinding prevExpectedType = pushExpectedType(expressionExpectedType); - CSExpression left = mapExpression(node.getLeftOperand()); - CSExpression right = mapExpression(node.getRightOperand()); + Expression leftOperand = node.getLeftOperand(); + Expression rightOperand = node.getRightOperand(); + + ITypeBinding prevExpectedType; + if(leftOperand.resolveTypeBinding().getName().equals("null") || + rightOperand.resolveTypeBinding().getName().equals("null")){ + // if one of operands is null - expected type for the operands is unknown (reference?) + prevExpectedType = pushExpectedType(resolveWellKnownType("void")); + }else{ + prevExpectedType = pushExpectedType(expressionExpectedType); + } + + CSExpression left = mapExpression(leftOperand); + CSExpression right = mapExpression(rightOperand); popExpectedType(prevExpectedType); String type = node.getLeftOperand().resolveTypeBinding().getQualifiedName(); if (node.getOperator() == InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED) { diff --git a/src/test/resources/autocasting/Boolean.cs.txt b/src/test/resources/autocasting/Boolean.cs.txt index 2e041b5..b842346 100644 --- a/src/test/resources/autocasting/Boolean.cs.txt +++ b/src/test/resources/autocasting/Boolean.cs.txt @@ -13,7 +13,7 @@ namespace autocasting { bool? val = true && _b; bool? res = resolve((bool)val, (bool)val || (x == 2)); - if ((bool)res != null) + if (res != null) { return (bool)res || (x == 3); } From 916087c8f2016191ccfbe33c6a5e7430f0b6eb11 Mon Sep 17 00:00:00 2001 From: ydanila Date: Wed, 1 Apr 2015 20:04:24 +0300 Subject: [PATCH 35/37] Support for long? -> double casting --- src/main/sharpen/core/CSharpBuilder.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 0ad824e..5ef6c97 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -3127,6 +3127,10 @@ private boolean canBeCastedTo(String actualTypeName, String expectedTypeName) { return expectedTypeName.equals("double"); } + if(actualTypeName.equals("long?")){ + return expectedTypeName.equals("double"); + } + if(actualTypeName.equals("int?")){ return expectedTypeName.equals("long"); } From 291761a490b45c51a7cd17c184be061833f934cf Mon Sep 17 00:00:00 2001 From: ydanila Date: Fri, 3 Apr 2015 12:22:49 +0300 Subject: [PATCH 36/37] Fix for the wrong casting conversion - introduced implicit conversion detection --- src/main/sharpen/core/CSharpBuilder.java | 30 +++++++++++++++------- src/test/resources/autocasting/Long.cs.txt | 2 +- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/main/sharpen/core/CSharpBuilder.java b/src/main/sharpen/core/CSharpBuilder.java index 5ef6c97..e04a58d 100644 --- a/src/main/sharpen/core/CSharpBuilder.java +++ b/src/main/sharpen/core/CSharpBuilder.java @@ -3066,12 +3066,19 @@ private CSExpression castToValueTypeIfNeeded(Expression node, ITypeBinding expec CSTypeReference mappedExpectedType = (CSTypeReference)mappedExpectedTypeReference; if (isNullableFor(mappedActualType, mappedExpectedType) || - canBeCastedTo(mappedActualType, mappedExpectedType) || - canBeCastedTo(valueTypeName(mappedActualType.typeName()), mappedExpectedType.typeName())) { + canBeCastedTo(mappedActualType, mappedExpectedType)) { return applyCast(expression, mappedExpectedType); } + if(isValueTypeClass(actualType)) { + String mappedActualValueTypeName = valueTypeName(mappedActualType.typeName()); + + if (canBeImplicitlyCastedTo(mappedActualValueTypeName, mappedExpectedType.typeName())) { + return applyCast(expression, new CSTypeReference(mappedActualValueTypeName)); + } + } + if(!hasParentCastExpression(node) && canBeUncheckedCastedTo(mappedActualType, mappedExpectedType)){ return uncheckedCast(mappedExpectedType.typeName(), expression); } @@ -3098,7 +3105,7 @@ private boolean isPrimitiveType(ITypeBinding type) { type.getQualifiedName().equals("boolean")); } - private boolean isNullableValueType(CSTypeReference type) { + private boolean isCSNullableValueType(CSTypeReference type) { return type.typeName().endsWith("?"); } @@ -3113,7 +3120,7 @@ private boolean isValueTypeClass(ITypeBinding type) { private boolean isNullableFor(CSTypeReference nullableType, CSTypeReference valueType) { - return isNullableValueType(nullableType) && valueTypeName(nullableType.typeName()).equals(valueType.typeName()); + return isCSNullableValueType(nullableType) && valueTypeName(nullableType.typeName()).equals(valueType.typeName()); } private boolean canBeCastedTo(CSTypeReference actualType, CSTypeReference expectedType) { @@ -3121,18 +3128,23 @@ private boolean canBeCastedTo(CSTypeReference actualType, CSTypeReference expect return canBeCastedTo(actualType.typeName(), expectedType.typeName()); } - private boolean canBeCastedTo(String actualTypeName, String expectedTypeName) { + private boolean canBeCastedTo(String csActualTypeName, String expectedTypeName) { - if(actualTypeName.equals("float?")){ + if(csActualTypeName.equals("float?")){ return expectedTypeName.equals("double"); } - if(actualTypeName.equals("long?")){ + if(csActualTypeName.equals("long?")){ return expectedTypeName.equals("double"); } - if(actualTypeName.equals("int?")){ - return expectedTypeName.equals("long"); + return false; + } + + private boolean canBeImplicitlyCastedTo(String csActualTypeName, String csExpectedTypeName) { + + if(csActualTypeName.equals("int")){ + return csExpectedTypeName.equals("long"); } return false; diff --git a/src/test/resources/autocasting/Long.cs.txt b/src/test/resources/autocasting/Long.cs.txt index 53c5cc7..6a502cf 100644 --- a/src/test/resources/autocasting/Long.cs.txt +++ b/src/test/resources/autocasting/Long.cs.txt @@ -29,7 +29,7 @@ namespace autocasting return 0; } int? i = 10; - autocasting.Autocasting obj = new autocasting.Autocasting((long)result, (long)i); + autocasting.Autocasting obj = new autocasting.Autocasting((long)result, (int)i); result = obj.longval(); return (long)result; } From 8ab60960973bb02ce81f34ca0bcc09e19be6bedf Mon Sep 17 00:00:00 2001 From: "moljac Miljenko Cvjetko)" Date: Thu, 27 Aug 2015 23:33:51 +0200 Subject: [PATCH 37/37] pom.xml fix for newer java version use by maven for errors like unsupported generics or annotations mavaen uses source 1.3 fix makes maven use 1.7 --- pom.xml | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/pom.xml b/pom.xml index 1098a2d..20eed80 100644 --- a/pom.xml +++ b/pom.xml @@ -132,6 +132,60 @@ + + + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + maven-assembly-plugin