From 4d7f6ff8300cc766bc2575e4e47bf1f95b0584af Mon Sep 17 00:00:00 2001 From: Mikhail Velikanov Date: Tue, 9 Aug 2022 14:41:55 +0300 Subject: [PATCH 1/2] Implemented translation of class literals. Also changes to STS grammar to allow underscores in numeric literals, and a number of fixes to translation of those literals. Added a test to cover all of the changes above. Change-Id: Ica33d0999a2f2212bc6e9c7109e94e93eb6dcdc9 Signed-off-by: Mikhail Velikanov --- .../ohos/migrator/java/JavaTransformer.java | 34 ++++++++++- .../ohos/migrator/staticTS/NodeBuilder.java | 24 ++++++-- .../migrator/staticTS/parser/StaticTSLexer.g4 | 30 +++++++--- migrator/test/java/literals.java | 58 +++++++++++++++++++ migrator/test/java/literals.java.sts | 50 ++++++++++++++++ 5 files changed, 179 insertions(+), 17 deletions(-) create mode 100644 migrator/test/java/literals.java create mode 100755 migrator/test/java/literals.java.sts diff --git a/migrator/src/com/ohos/migrator/java/JavaTransformer.java b/migrator/src/com/ohos/migrator/java/JavaTransformer.java index b0eb95d5a..8f03a6ce5 100644 --- a/migrator/src/com/ohos/migrator/java/JavaTransformer.java +++ b/migrator/src/com/ohos/migrator/java/JavaTransformer.java @@ -771,9 +771,10 @@ public class JavaTransformer extends ASTVisitor implements Transformer { @Override public boolean visit(ArrayType javaArrayType) { - pushCurrent(new PrimaryTypeContext(stsCurrent, 0)); - pushCurrent(new ArrayTypeContext(stsCurrent, 0)); + boolean needPrimaryType = isInPrimaryTypeContext(); + if (needPrimaryType) pushCurrent(new PrimaryTypeContext(stsCurrent, 0)); + pushCurrent(new ArrayTypeContext(stsCurrent, 0)); javaArrayType.getElementType().accept(this); int numDims = javaArrayType.getDimensions(); @@ -783,8 +784,8 @@ public class JavaTransformer extends ASTVisitor implements Transformer { } popCurrent(); // ArrayTypeContext - popCurrent(); // PrimaryTypeContext + if (needPrimaryType) popCurrent(); // PrimaryTypeContext return false; } @@ -1672,12 +1673,39 @@ public class JavaTransformer extends ASTVisitor implements Transformer { return false; } + // Java AST: + // TypeName {[ ]} . class + // NumericType {[ ]} . class + // boolean {[ ]} . class + // void . class + // STS AST: + // SingleExpressionContext + // ClassLiteralExpressionContext + // PrimaryTypeContext . class + @Override + public boolean visit(TypeLiteral node) { + pushCurrent(new ClassLiteralExpressionContext(pushSingleExpression())); + + // Translate type + node.getType().accept(this); + + // Add . and class tokens + stsCurrent.addChild(NodeBuilder.terminalNode(StaticTSParser.Dot)); + stsCurrent.addChild(NodeBuilder.terminalNode(StaticTSParser.Class)); + + popSingleExpression(); // ClassLiteralExpressionContext + + ++countExprTransformed; + return false; + } + // Java tree: // ExpressionStatement: // Expression ; // STS tree: // expressionStatement: // singleExpression SemiColon? + @Override public boolean visit(ExpressionStatement javaExprStmt) { pushStatement(new ExpressionStatementContext(null, 0)); javaExprStmt.getExpression().accept(this); diff --git a/migrator/src/com/ohos/migrator/staticTS/NodeBuilder.java b/migrator/src/com/ohos/migrator/staticTS/NodeBuilder.java index 65ca0b0af..dd2ad47c5 100644 --- a/migrator/src/com/ohos/migrator/staticTS/NodeBuilder.java +++ b/migrator/src/com/ohos/migrator/staticTS/NodeBuilder.java @@ -180,16 +180,28 @@ public class NodeBuilder { LiteralContext stsLiteral = new LiteralContext(null, 0); CommonToken token; + // parse string representation to create appropriate token - if (value.startsWith("0b")) { + // Ignore suffices (d, f, l) that Java allows for numeric literals + if (value.endsWith("f") || value.endsWith("F") || + value.endsWith("d") || value.endsWith("D") || + value.endsWith("l") || value.endsWith("L")) { + value = value.substring(0, value.length() - 1); + } + + if (value.startsWith("0b") || value.startsWith("0B")) { token = new CommonToken(StaticTSParser.BinaryIntegerLiteral, value); - } else if (value.startsWith("0x")) { + } + else if (value.startsWith("0x") || value.startsWith("0X")) { token = new CommonToken(StaticTSParser.HexIntegerLiteral, value); - } else if( value.startsWith("0") && !value.contains("89")) { + } + else if (value.startsWith("0") && value.length() > 1 && + !value.contains("89") && !value.contains(".")) { + // STS octal literals start with 0o + value = "0o" + value.substring(1); token = new CommonToken(StaticTSParser.OctalIntegerLiteral, value); - } else { - // Java floats have suffix 'f' - if (value.endsWith("f")) value = value.substring(0,value.length()-1); + } + else { token = new CommonToken(StaticTSParser.DecimalLiteral, value); } diff --git a/migrator/src/com/ohos/migrator/staticTS/parser/StaticTSLexer.g4 b/migrator/src/com/ohos/migrator/staticTS/parser/StaticTSLexer.g4 index 705a2583c..b0ba23ccc 100644 --- a/migrator/src/com/ohos/migrator/staticTS/parser/StaticTSLexer.g4 +++ b/migrator/src/com/ohos/migrator/staticTS/parser/StaticTSLexer.g4 @@ -86,16 +86,25 @@ BooleanLiteral: 'true' /// Numeric Literals -DecimalLiteral: DecimalIntegerLiteral '.' [0-9]* ExponentPart? - | '.' [0-9]+ ExponentPart? +DecimalLiteral: DecimalIntegerLiteral '.' FractionalPart? ExponentPart? + | '.' FractionalPart ExponentPart? | DecimalIntegerLiteral ExponentPart? ; /// Numeric Literals -HexIntegerLiteral: '0' [xX] HexDigit+; -OctalIntegerLiteral: '0' [oO] [0-7]+ {!this.IsStrictMode()}?; -BinaryIntegerLiteral: '0' [bB] [01]+; +HexIntegerLiteral: '0' [xX] ( + HexDigit + | HexDigit (HexDigit | '_')* HexDigit + ); +OctalIntegerLiteral: '0' [oO] ( + [0-7] + | [0-7] [0-7_]* [0-7] + ); +BinaryIntegerLiteral: '0' [bB] ( + [01] + | [01] [01_]* [01] + ); /// Keywords @@ -240,12 +249,17 @@ fragment HexDigit ; fragment DecimalIntegerLiteral - : '0' - | [1-9] [0-9]* + : [0-9] + | [1-9] [0-9_]* [0-9] + ; + +fragment FractionalPart + : [0-9] + | [0-9] [0-9_]* [0-9] ; fragment ExponentPart - : [eE] [+-]? [0-9]+ + : [eE] [+-]? DecimalIntegerLiteral ; fragment IdentifierPart diff --git a/migrator/test/java/literals.java b/migrator/test/java/literals.java new file mode 100644 index 000000000..a49ec627e --- /dev/null +++ b/migrator/test/java/literals.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.migrator.test.java; + +class literals { + void test() { + // integer literals + byte b = 0; + byte b2 = 1_0_2; + short s = 0x1; + short s2 = 0X1_A; + int i = 02; + int i2 = 03_4_56; + long l = 0b11L; + long l2 = 0B1_01_11l; + + // floating-point literals + float f = 4f; + float f2 = 1_2.23_45e+6F; + float f3 = 3.402_823_5e1_7f; + double d = 5.; + double d2 = .123_456; + double d3 = 0.123876; + double pi = 3.1416D; + double G = 6.6_73_00E-11d; + + // char and string literals + char c = '6'; + char c2 = '\t'; + char c3 = '\''; + String str = "7"; + String str2 = "Who needs \"dots\" over \"eyes\"? ;)\r\n"; + + // null and boolean literals + literals nl = null; + boolean tl = true; + boolean fl = false; + + // class literals + Class cl = literals.class; + Class ll = long.class; + Class sal = String[].class; + Class dal = double[].class; + } +} diff --git a/migrator/test/java/literals.java.sts b/migrator/test/java/literals.java.sts new file mode 100755 index 000000000..34c2abd0d --- /dev/null +++ b/migrator/test/java/literals.java.sts @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.migrator.test.java; + +open class literals { + open test(): void { + let b : byte = 0; + let b2 : byte = 1_0_2; + let s : short = 0x1; + let s2 : short = 0X1_A; + let i : int = 0o2; + let i2 : int = 0o3_4_56; + let l : long = 0b11; + let l2 : long = 0B1_01_11; + let f : float = 4; + let f2 : float = 1_2.23_45e+6; + let f3 : float = 3.402_823_5e1_7; + let d : double = 5.; + let d2 : double = .123_456; + let d3 : double = 0.123876; + let pi : double = 3.1416; + let G : double = 6.6_73_00E-11; + let c : char = '6'; + let c2 : char = '\t'; + let c3 : char = '\''; + let str : String = "7"; + let str2 : String = "Who needs \"dots\" over \"eyes\"? ;)\r\n"; + let nl : literals = null; + let tl : boolean = true; + let fl : boolean = false; + let cl : Class = literals.class; + let ll : Class = long.class; + let sal : Class = String[].class; + let dal : Class = double[].class; + } +} + -- Gitee From bc8e4febd8c2839c87ba698a6d06e5d905bcb713 Mon Sep 17 00:00:00 2001 From: Mikhail Velikanov Date: Tue, 9 Aug 2022 17:40:18 +0300 Subject: [PATCH 2/2] Minor fix to translation of numeric literals: Don't chop off terminating F in hexadecimal literals (was being taken for the f suffix earlier). Change-Id: I712151db5b5d88d9c6b9fe0e339886e2778b6eec Signed-off-by: Mikhail Velikanov --- .../src/com/ohos/migrator/staticTS/NodeBuilder.java | 10 +++++++--- migrator/test/java/literals.java | 2 +- migrator/test/java/literals.java.sts | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/migrator/src/com/ohos/migrator/staticTS/NodeBuilder.java b/migrator/src/com/ohos/migrator/staticTS/NodeBuilder.java index dd2ad47c5..aa327e05e 100644 --- a/migrator/src/com/ohos/migrator/staticTS/NodeBuilder.java +++ b/migrator/src/com/ohos/migrator/staticTS/NodeBuilder.java @@ -182,9 +182,10 @@ public class NodeBuilder { CommonToken token; // parse string representation to create appropriate token - // Ignore suffices (d, f, l) that Java allows for numeric literals - if (value.endsWith("f") || value.endsWith("F") || - value.endsWith("d") || value.endsWith("D") || + // Ignore d and l suffices that Java allows for numeric literals + // NOTE: The f suffix that Java also allows will be dealt with + // later, as it might conflict with hexadecimal literals. + if (value.endsWith("d") || value.endsWith("D") || value.endsWith("l") || value.endsWith("L")) { value = value.substring(0, value.length() - 1); } @@ -202,6 +203,9 @@ public class NodeBuilder { token = new CommonToken(StaticTSParser.OctalIntegerLiteral, value); } else { + if (value.endsWith("f") || value.endsWith("F")) { + value = value.substring(0, value.length() - 1); + } token = new CommonToken(StaticTSParser.DecimalLiteral, value); } diff --git a/migrator/test/java/literals.java b/migrator/test/java/literals.java index a49ec627e..5c8c11a6b 100644 --- a/migrator/test/java/literals.java +++ b/migrator/test/java/literals.java @@ -21,7 +21,7 @@ class literals { byte b = 0; byte b2 = 1_0_2; short s = 0x1; - short s2 = 0X1_A; + short s2 = 0X1_F; int i = 02; int i2 = 03_4_56; long l = 0b11L; diff --git a/migrator/test/java/literals.java.sts b/migrator/test/java/literals.java.sts index 34c2abd0d..3e3d7934d 100755 --- a/migrator/test/java/literals.java.sts +++ b/migrator/test/java/literals.java.sts @@ -20,7 +20,7 @@ open class literals { let b : byte = 0; let b2 : byte = 1_0_2; let s : short = 0x1; - let s2 : short = 0X1_A; + let s2 : short = 0X1_F; let i : int = 0o2; let i2 : int = 0o3_4_56; let l : long = 0b11; -- Gitee