diff --git a/README.md b/README.md index 7a17bdc..6e24fe0 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ [imazen/sharpen](https://github.com/imazen/sharpen) [![master](https://img.shields.io/travis/imazen/sharpen/master.svg?label=imazen%20master)](https://travis-ci.org/imazen/sharpen/builds)[![imazen master - AppVeyor](https://ci.appveyor.com/api/projects/status/qxrbmyx70iuoev0x/branch/master?svg=true&passingText=imazen%20master%20-%20passing&failingText=imazen%20master%20-%20failed)](https://ci.appveyor.com/project/imazen/sharpen/branch/master) [![develop](https://img.shields.io/travis/imazen/sharpen/develop.svg?label=imazen%20develop)](https://travis-ci.org/imazen/sharpen/builds) [![imazen develop - AppVeyor](https://ci.appveyor.com/api/projects/status/qxrbmyx70iuoev0x/branch/develop?svg=true&passingText=imazen%20develop%20-%20passing&failingText=imazen%20develop%20-%20failed)](https://ci.appveyor.com/project/imazen/sharpen/branch/develop) -[slluis/sharpen](https://github.com/imazen/sharpen) [![master](https://img.shields.io/travis/slluis/sharpen/master.svg?label=slluis%20master)](https://travis-ci.org/slluis/sharpen/builds)[![slluis master - AppVeyor](https://ci.appveyor.com/api/projects/status/[projectid]/branch/master?svg=true&passingText=slluis%20master%20-%20passing&failingText=slluis%20master%20-%20failed)](https://ci.appveyor.com/project/slluis/sharpen/branch/master) [![develop](https://img.shields.io/travis/slluis/sharpen/develop.svg?label=slluis%20develop)](https://travis-ci.org/slluis/sharpen/builds) -[![slluis develop - AppVeyor](https://ci.appveyor.com/api/projects/status/[projectid]/branch/develop?svg=true&passingText=slluis%20develop%20-%20passing&failingText=slluis%20develop%20-%20failed)](https://ci.appveyor.com/project/slluis/sharpen/branch/develop) +[mono/sharpen](https://github.com/mono/sharpen) [![master](https://img.shields.io/travis/mono/sharpen/master.svg?label=mono%20master)](https://travis-ci.org/mono/sharpen/builds)[![mono master - AppVeyor (permissions issue)](https://ci.appveyor.com/api/projects/status/[projectid]/branch/master?svg=true&passingText=slluis%20master%20-%20passing&failingText=slluis%20master%20-%20failed)](https://ci.appveyor.com/project/imazen/imazen/branch/master) [![develop](https://img.shields.io/travis/mono/sharpen/develop.svg?label=mono%20develop)](https://travis-ci.org/mono/sharpen/builds) +[![mono develop - AppVeyor (permissions issue)](https://ci.appveyor.com/api/projects/status/[projectid]/branch/develop?svg=true&passingText=mono%20develop%20-%20passing&failingText=mono%20develop%20-%20failed)](https://ci.appveyor.com/project/mono/sharpen/branch/develop) @@ -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/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 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 f72f446..e04a58d 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; @@ -1491,13 +1530,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 +1553,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); @@ -1751,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); @@ -1772,6 +1812,7 @@ else if (method.name().equals("TearDown")) { } } } + popExpectedType(savedType); } private void cleanBaseSetupCalls (CSMethod method) { @@ -1798,9 +1839,8 @@ private void mapMethodParts(MethodDeclaration node, CSMethodBase method) { _currentType.addMember(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); @@ -2100,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); } @@ -2114,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; } @@ -2133,8 +2173,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; } @@ -2148,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); } @@ -2398,7 +2446,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; } @@ -2407,14 +2455,26 @@ public boolean visit(NumberLiteral node) { String token = node.getToken(); CSExpression literal = new CSNumberLiteralExpression(token); - if (expectingType ("byte") && token.startsWith("-")) { - literal = uncheckedCast ("byte",literal); + if (hasParentCastExpression(node)) { + ITypeBinding castTypeBinding = getParentCastType(node).resolveBinding(); + if(!isInRange(castTypeBinding, token)){ + literal = uncheckedCast (mappedTypeName(castTypeBinding.getName()), literal); + } + } + else if (expectingType ("byte") && token.startsWith("-")) { + literal = uncheckedCast (mappedTypeName("byte"),literal); } else if (token.startsWith("0x")) { - if (token.endsWith("l") || token.endsWith("L")) { - literal = uncheckedCast("long", literal); + 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(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))) { @@ -2430,7 +2490,25 @@ else if (token.startsWith("0x")) { return false; } - private CSUncheckedExpression uncheckedCast(String type, CSExpression expression) { + private boolean hasParentCastExpression(Expression node) { + return (node.getParent() instanceof CastExpression); + } + + private Type getParentCastType(Expression 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))); } @@ -2612,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)); } @@ -2681,7 +2759,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) @@ -2718,18 +2796,60 @@ 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()); + ITypeBinding actualType = node.resolveTypeBinding(); + String mappedActualTypeName = mappedTypeName(actualType); + if(isSameTypeCast(expression, mappedActualTypeName)) { + pushExpression(expression); + } + 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")) + pushExpression(new CSUncheckedExpression (popExpression())); + } return false; } - public boolean visit(PrefixExpression node) { + 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(); + } + if (!(castExpression instanceof CSCastExpression)) { + return false; + } + return castTypeName((CSCastExpression)castExpression).equals(expectedCSType); + } + + 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) { - expr = uncheckedCast ("byte", expr); + expr = uncheckedCast (mappedTypeName("byte"), expr); } pushExpression(expr); return false; @@ -2742,8 +2862,23 @@ public boolean visit(PostfixExpression node) { public boolean visit(InfixExpression node) { - CSExpression left = mapExpression(node.getLeftOperand()); - CSExpression right = mapExpression(node.getRightOperand()); + ITypeBinding expressionExpectedType = node.resolveTypeBinding(); + + 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) { if (type.equals ("byte")) { @@ -2779,14 +2914,15 @@ 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; } public boolean visit(InstanceofExpression node) { pushExpression(new CSInfixExpression("is", mapExpression(node.getLeftOperand()), mappedTypeReference(node - .getRightOperand().resolveBinding()))); + .getRightOperand().resolveBinding()))); return false; } @@ -2830,12 +2966,12 @@ 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); field.addModifier(CSFieldModifier.Readonly); - mapAnnotations(node, field); + mapAnnotations(node.modifiers(), field); mapDocumentation(node, field); popExpectedType(saved); @@ -2874,13 +3010,21 @@ public boolean visit(Assignment node) { } private CSExpression mapExpression(ITypeBinding expectedType, Expression expression) { - if (expectedType != null) - return castIfNeeded(expectedType, expression.resolveTypeBinding(), mapExpression(expression)); + if (null == expression) + return null; + + if (expectedType != null && expectedType != resolveWellKnownType("void")) + 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")); } @@ -2888,15 +3032,139 @@ 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) + if (expectedType == charType) { + if (actualType == expectedType) + return expression; + + return new CSCastExpression(mappedTypeReference(expectedType), expression); + } + + return castToValueTypeIfNeeded(node, expectedType, expression); + } + + private CSExpression castToValueTypeIfNeeded(Expression node, ITypeBinding expectedType, CSExpression expression) { + if(expectedType == null){ return expression; - return new CSCastExpression(mappedTypeReference(expectedType), expression); + } + + ITypeBinding actualType = node.resolveTypeBinding(); + + if (isPrimitiveType(actualType) || isValueTypeClass(actualType)) { + + CSTypeReferenceExpression mappedActualTypeReference = mappedTypeReference(actualType); + CSTypeReferenceExpression mappedExpectedTypeReference = mappedTypeReference(expectedType); + + if (isSameTypeCast(expression, mappedTypeName(expectedType))) { + return expression; + } + + if (!(mappedActualTypeReference instanceof CSTypeReference) || !(mappedExpectedTypeReference instanceof CSTypeReference)) { + return expression; + } + + CSTypeReference mappedActualType = (CSTypeReference)mappedActualTypeReference; + CSTypeReference mappedExpectedType = (CSTypeReference)mappedExpectedTypeReference; + + if (isNullableFor(mappedActualType, mappedExpectedType) || + 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); + } + } + + 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") || + type.getQualifiedName().equals("integer") || + type.getQualifiedName().equals("long") || + type.getQualifiedName().equals("float") || + type.getQualifiedName().equals("boolean")); + } + + private boolean isCSNullableValueType(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") || + type.getQualifiedName().equals("java.lang.Long") || + type.getQualifiedName().equals("java.lang.Float") || + type.getQualifiedName().equals("java.lang.Boolean")); + } + + private boolean isNullableFor(CSTypeReference nullableType, CSTypeReference valueType) { + + return isCSNullableValueType(nullableType) && valueTypeName(nullableType.typeName()).equals(valueType.typeName()); + } + + private boolean canBeCastedTo(CSTypeReference actualType, CSTypeReference expectedType) { + + return canBeCastedTo(actualType.typeName(), expectedType.typeName()); + } + + private boolean canBeCastedTo(String csActualTypeName, String expectedTypeName) { + + if(csActualTypeName.equals("float?")){ + return expectedTypeName.equals("double"); + } + + if(csActualTypeName.equals("long?")){ + return expectedTypeName.equals("double"); + } + + return false; + } + + private boolean canBeImplicitlyCastedTo(String csActualTypeName, String csExpectedTypeName) { + + if(csActualTypeName.equals("int")){ + return csExpectedTypeName.equals("long"); + } + + 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<"); + return t.getName().startsWith("List<") || t.getName().startsWith("Set<") + || t.getName().startsWith("Collection<"); } private boolean isSubclassOf (ITypeBinding t, ITypeBinding tbase) { @@ -2920,10 +3188,16 @@ 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()); + ITypeBinding[] constructorArgsTypes = node.resolveConstructorBinding().getParameterTypes(); + mapArguments(expression, constructorArgsTypes, node.arguments()); pushExpression(expression); return false; } @@ -3025,7 +3299,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; } @@ -3432,7 +3706,7 @@ private void processMappedMethodInvocation(MethodInvocation node, IMethodBinding mie.addArgument(expression); } } - mapArguments(mie, arguments); + mapArguments(mie, node.resolveMethodBinding().getParameterTypes(), arguments); adjustJUnitArguments(mie, node); pushExpression(mie); } @@ -3494,9 +3768,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); } } @@ -3543,31 +3817,34 @@ 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())) { - if (cls != null) { - pushExpression(new CSMemberReferenceExpression(mappedTypeReference(cls), ident)); - return false; - } + resultExpression = new CSMemberReferenceExpression(mappedTypeReference(cls), ident); } - else if (cls.isEnum() && ident.indexOf('.') == -1){ - pushExpression(new CSMemberReferenceExpression(mappedTypeReference(cls), ident)); - return false; + else if (cls.isEnum() && ident.indexOf('.') == -1 && vb.isEnumConstant()){ + 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 + + pushExpression(castToValueTypeIfNeeded(node, _currentExpectedType, resultExpression)); } return false; } - private void addStatement(CSStatement statement) { + private void addStatement(CSStatement statement) { _currentBlock.addStatement(statement); } @@ -3745,7 +4022,10 @@ private CSExpression popExpression() { } private CSVariableDeclaration createParameter(SingleVariableDeclaration declaration) { - return createVariableDeclaration(declaration.resolveBinding(), null); + CSVariableDeclaration varDeclaration = createVariableDeclaration(declaration.resolveBinding(), null); + varDeclaration.isVarArgs(declaration.isVarargs()); + mapAnnotations(declaration.modifiers(), varDeclaration); + return varDeclaration; } protected void visit(List nodes) { @@ -4073,8 +4353,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) { diff --git a/src/main/sharpen/core/Configuration.java b/src/main/sharpen/core/Configuration.java index a69e8b7..a925b64 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; @@ -191,7 +198,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) { @@ -365,7 +372,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); } @@ -377,6 +388,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)); @@ -385,8 +400,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; } @@ -398,6 +417,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); @@ -572,9 +595,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/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/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 aa617ae..86c8930 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(); @@ -238,7 +250,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 645f533..0513a80 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 931b1b4..012e50b 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(); diff --git a/src/main/sharpen/core/csharp/CSharpPrinter.java b/src/main/sharpen/core/csharp/CSharpPrinter.java index 58c879f..6e70615 100644 --- a/src/main/sharpen/core/csharp/CSharpPrinter.java +++ b/src/main/sharpen/core/csharp/CSharpPrinter.java @@ -305,9 +305,20 @@ private boolean isExplicitMember(CSMember member) { } public void visit(CSVariableDeclaration node) { - node.type().accept(this); + if(node.attributes().size() > 0) { + writeAttributes(node); + write(" "); + } + if(node.isVarArgs()) { + write("params "); + } + if(node.declareType()) { + node.type().accept(this); + } if (null != node.name()) { - write(" "); + if(node.declareType()) { + write(" "); + } write(node.name()); } if (null != node.initializer()) { @@ -413,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) { @@ -435,7 +446,7 @@ public void visit(CSLineComment node) { @Override public void visit(CSBlockComment node) { for(String line : node.lines()){ - writeIndentedLine(line); + writeLine(line); } } @@ -786,18 +797,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(")"); } @@ -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/CSAttributesContainer.java b/src/main/sharpen/core/csharp/ast/CSAttributesContainer.java new file mode 100644 index 0000000..ce27ce3 --- /dev/null +++ b/src/main/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/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/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/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/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/CSVariableAttribute.java b/src/main/sharpen/core/csharp/ast/CSVariableAttribute.java new file mode 100644 index 0000000..4587b75 --- /dev/null +++ b/src/main/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/src/main/sharpen/core/csharp/ast/CSVariableDeclaration.java b/src/main/sharpen/core/csharp/ast/CSVariableDeclaration.java index 7a30e6e..88ed454 100644 --- a/src/main/sharpen/core/csharp/ast/CSVariableDeclaration.java +++ b/src/main/sharpen/core/csharp/ast/CSVariableDeclaration.java @@ -21,13 +21,20 @@ 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(); + private boolean _isVarArgs; + private boolean _declareType = true; + + public CSVariableDeclaration(String name, CSTypeReferenceExpression type) { this(name, type, null); } @@ -64,4 +71,41 @@ 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); + } + + public void isVarArgs(boolean isVarArgs) { + _isVarArgs = isVarArgs; + } + + public boolean isVarArgs() { + return _isVarArgs; + } + + public boolean declareType() { + return _declareType; + } + + public void declareType(boolean declareType) { + _declareType = declareType; + } } 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/Enum2.cs.txt b/src/test/resources/Enum2.cs.txt new file mode 100644 index 0000000..4ff5253 --- /dev/null +++ b/src/test/resources/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/src/test/resources/Enum2.java.txt b/src/test/resources/Enum2.java.txt new file mode 100644 index 0000000..e3800ee --- /dev/null +++ b/src/test/resources/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/test/resources/For3.cs.txt b/src/test/resources/For3.cs.txt new file mode 100644 index 0000000..3bff49a --- /dev/null +++ b/src/test/resources/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/src/test/resources/For3.java.txt b/src/test/resources/For3.java.txt new file mode 100644 index 0000000..9f92f26 --- /dev/null +++ b/src/test/resources/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/test/resources/annotations/MethodAnnotation.cs.txt b/src/test/resources/annotations/MethodAnnotation.cs.txt new file mode 100644 index 0000000..36b5a70 --- /dev/null +++ b/src/test/resources/annotations/MethodAnnotation.cs.txt @@ -0,0 +1,15 @@ +namespace annotations +{ + internal class Annotated + { + [annotations.TestAnnotation] + public virtual void annotatedMethod([annotations.NotNull] string name) + { + } + + public virtual void annotatedMethodWithVarAgs([annotations.NotNull] params string + [] names) + { + } + } +} \ No newline at end of file diff --git a/src/test/resources/annotations/MethodAnnotation.java.txt b/src/test/resources/annotations/MethodAnnotation.java.txt new file mode 100644 index 0000000..a93c00d --- /dev/null +++ b/src/test/resources/annotations/MethodAnnotation.java.txt @@ -0,0 +1,16 @@ +package annotations; + +@interface TestAnnotation { +} + +@interface NotNull { +} + +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/test/resources/annotations/SimpleAnnotationMapping.cs.txt b/src/test/resources/annotations/SimpleAnnotationMapping.cs.txt new file mode 100644 index 0000000..51ee235 --- /dev/null +++ b/src/test/resources/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/src/test/resources/annotations/SimpleAnnotationMapping.java.txt b/src/test/resources/annotations/SimpleAnnotationMapping.java.txt new file mode 100644 index 0000000..c758583 --- /dev/null +++ b/src/test/resources/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/resources/autocasting/Boolean.cs.txt b/src/test/resources/autocasting/Boolean.cs.txt new file mode 100644 index 0000000..b842346 --- /dev/null +++ b/src/test/resources/autocasting/Boolean.cs.txt @@ -0,0 +1,35 @@ +namespace autocasting +{ + internal class Autocasting + { + private bool _b; + + private Autocasting(bool b) + { + _b = b; + } + + public virtual bool booleanval(int x) + { + bool? val = true && _b; + bool? res = resolve((bool)val, (bool)val || (x == 2)); + if (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; + } + autocasting.Autocasting obj = new autocasting.Autocasting((bool)result); + result = obj.booleanval(10); + 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..a16b416 --- /dev/null +++ b/src/test/resources/autocasting/Boolean.java.txt @@ -0,0 +1,29 @@ +package autocasting; + +class Autocasting { + + private boolean _b; + private Autocasting(boolean b){ + _b = b; + } + + public boolean booleanval(int x){ + Boolean val = true && _b; + 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; + + Autocasting obj = new Autocasting(result); + result = obj.booleanval(10); + return result; + } +} \ No newline at end of file diff --git a/src/test/resources/autocasting/Char.cs.txt b/src/test/resources/autocasting/Char.cs.txt index 2dd0d06..7727e68 100644 --- a/src/test/resources/autocasting/Char.cs.txt +++ b/src/test/resources/autocasting/Char.cs.txt @@ -4,9 +4,23 @@ 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 ' '; + } + + 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 ab473d4..adaf0f4 100644 --- a/src/test/resources/autocasting/Char.java.txt +++ b/src/test/resources/autocasting/Char.java.txt @@ -3,7 +3,21 @@ package autocasting; class CharAutocasting { private char _ch; - private void test() { + private char test() { this._ch = 1; + + switch (this._ch) + { + case 0x0022: + return 0x0033; + } + + return ' '; } + + public char ch(int index) + { + String str = "teststr"; + return index < str.length() ? str.charAt(index) : 0x0000; + } } \ No newline at end of file diff --git a/src/test/resources/autocasting/Double.cs.txt b/src/test/resources/autocasting/Double.cs.txt new file mode 100644 index 0000000..ce5ea97 --- /dev/null +++ b/src/test/resources/autocasting/Double.cs.txt @@ -0,0 +1,36 @@ +namespace autocasting +{ + internal class Autocasting + { + private double _d; + + private Autocasting(double d) + { + _d = d; + } + + public virtual double dbl() + { + double? val = 110.00 + _d; + double? res = minus((double)val, (double)val / 2); + if (res != null) + { + return (double)res + 5; + } + return 0; + } + + private double minus(double arg1, double arg2) + { + double? result = arg1 - arg2; + double test = (double)result + 4; + if (test < 0) + { + return 0; + } + autocasting.Autocasting obj = new autocasting.Autocasting((double)result); + result = obj.dbl(); + return (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 new file mode 100644 index 0000000..b77c471 --- /dev/null +++ b/src/test/resources/autocasting/Double.java.txt @@ -0,0 +1,30 @@ +package autocasting; + +class Autocasting { + + private double _d; + private Autocasting(double d){ + _d = d; + } + + public double dbl(){ + Double val = 110.00 + _d; + Double res = minus(val, val / 2); + if(res != null){ + return res + 5; + } + + return 0; + } + + private double minus(double arg1, double arg2){ + Double result = arg1 - arg2; + double test = result + 4; + 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 new file mode 100644 index 0000000..0ea9e01 --- /dev/null +++ b/src/test/resources/autocasting/Float.cs.txt @@ -0,0 +1,37 @@ +namespace autocasting +{ + internal class Autocasting + { + private float _f; + + private Autocasting(float f, double d) + { + _f = f + (float)d; + } + + public virtual float floatval() + { + float? val = 110.0F + _f; + 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; + } + autocasting.Autocasting obj = new autocasting.Autocasting((float)result, (double) + result); + result = obj.floatval(); + 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..bf665ba --- /dev/null +++ b/src/test/resources/autocasting/Float.java.txt @@ -0,0 +1,30 @@ +package autocasting; + +class Autocasting { + + private float _f; + private Autocasting(float f, double d){ + _f = f + (float)d; + } + + public float floatval(){ + Float val = 110.0F + _f; + 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; + + Autocasting obj = new Autocasting(result, result); + result = obj.floatval(); + return result; + } +} \ No newline at end of file diff --git a/src/test/resources/autocasting/Hex.cs.txt b/src/test/resources/autocasting/Hex.cs.txt index 2a0a3ea..814000a 100644 --- a/src/test/resources/autocasting/Hex.cs.txt +++ b/src/test/resources/autocasting/Hex.cs.txt @@ -10,6 +10,16 @@ namespace autocasting withLong(unchecked((long)(0xabl))); } + public virtual void withCastDefined() + { + withShort((short)0x00FF); + withShort(unchecked((short)(0xFF00))); + withInt((int)0xab); + withLong((int)0xab); + withLong((long)0xabL); + withLong((long)0xabL); + } + private void withLong(long l) { } @@ -17,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 544068f..ea6c28e 100644 --- a/src/test/resources/autocasting/Hex.java.txt +++ b/src/test/resources/autocasting/Hex.java.txt @@ -9,9 +9,21 @@ public class Hex { withLong(0xabl); } + public void withCastDefined() { + withShort((short)0x00FF); + withShort((short)0xFF00); + withInt((int)0xab); + withLong((int)0xab); + withLong((long)0xabL); + withLong((long)0xabL); + } + private void withLong(long l) { } private void withInt(int i) { } + + private void withShort(short i) { + } } \ 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..29a2f24 --- /dev/null +++ b/src/test/resources/autocasting/Integer.cs.txt @@ -0,0 +1,38 @@ +namespace autocasting +{ + internal class Autocasting + { + private int _i; + + private Autocasting(int i, int i2) + { + _i = i; + } + + public virtual int integer() + { + int? val = 110 + _i; + int? res = minus((int)val, (int)val / 2); + if (res != null) + { + return (int)res + 5; + } + long l = 100L; + _i += unchecked((int)(l)); + return _i; + } + + private int minus(int arg1, int arg2) + { + int? result = arg1 - arg2; + int test = (int)result + 4; + if (test < 0) + { + return 0; + } + autocasting.Autocasting obj = new autocasting.Autocasting((int)result, (int)test); + result = obj.integer(); + 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..33d09bb --- /dev/null +++ b/src/test/resources/autocasting/Integer.java.txt @@ -0,0 +1,32 @@ +package autocasting; + +class Autocasting { + + private int _i; + private Autocasting(int i, int i2){ + _i = i; + } + + public int integer(){ + Integer val = 110 + _i; + Integer res = minus(val, val / 2); + if(res != null){ + return res + 5; + } + + long l = 100L; + _i += l; + return _i; + } + + private int minus(int arg1, int arg2){ + Integer result = arg1 - arg2; + int test = result + 4; + if(test < 0) + return 0; + + Autocasting obj = new Autocasting(result, (Integer)test); + 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 new file mode 100644 index 0000000..6a502cf --- /dev/null +++ b/src/test/resources/autocasting/Long.cs.txt @@ -0,0 +1,37 @@ +namespace autocasting +{ + internal class Autocasting + { + private long _l; + + private Autocasting(long l, long l2) + { + _l = l + l2; + } + + public virtual long longval() + { + long? val = 110L + _l; + 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; + } + int? i = 10; + autocasting.Autocasting obj = new autocasting.Autocasting((long)result, (int)i); + result = obj.longval(); + 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..1da37b6 --- /dev/null +++ b/src/test/resources/autocasting/Long.java.txt @@ -0,0 +1,31 @@ +package autocasting; + +class Autocasting { + + private long _l; + private Autocasting(long l, long l2){ + _l = l + l2; + } + + public long longval(){ + Long val = 110L + _l; + 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; + + Integer i = 10; + Autocasting obj = new Autocasting(result, i); + result = obj.longval(); + return result; + } +} \ No newline at end of file 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/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; 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; } 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; 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); } } diff --git a/src/test/resources/interfaces/IInterfaceToClass.cs.txt b/src/test/resources/interfaces/IInterfaceToClass.cs.txt new file mode 100644 index 0000000..34500e0 --- /dev/null +++ b/src/test/resources/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/src/test/resources/interfaces/InterfaceToClass.java.txt b/src/test/resources/interfaces/InterfaceToClass.java.txt new file mode 100644 index 0000000..60be6af --- /dev/null +++ b/src/test/resources/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/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 diff --git a/src/test/sharpen/ui/tests/AnnotationsTestCase.java b/src/test/sharpen/ui/tests/AnnotationsTestCase.java index bcefb17..c581279 100644 --- a/src/test/sharpen/ui/tests/AnnotationsTestCase.java +++ b/src/test/sharpen/ui/tests/AnnotationsTestCase.java @@ -13,6 +13,16 @@ 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 testMethodAnnotationMapping() throws IOException, CoreException { + runResourceTestCase("MethodAnnotation"); + } @Test public void testCompilerAnnotations() throws IOException, CoreException { @@ -28,6 +38,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; } } diff --git a/src/test/sharpen/ui/tests/AutoCastingTestCase.java b/src/test/sharpen/ui/tests/AutoCastingTestCase.java index 594dfae..9b6d7ec 100644 --- a/src/test/sharpen/ui/tests/AutoCastingTestCase.java +++ b/src/test/sharpen/ui/tests/AutoCastingTestCase.java @@ -19,21 +19,58 @@ 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?"); + 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; + } + @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"); + } + + @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"); + } +} 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; 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(); diff --git a/src/test/sharpen/ui/tests/UnclassifiedConversionTestCase.java b/src/test/sharpen/ui/tests/UnclassifiedConversionTestCase.java index d906ae1..bd6d94b 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 { @@ -181,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 {