diff --git a/org.eclipse.xtend.core.tests/src/org/eclipse/xtend/core/tests/compiler/AbstractXbaseEvaluationTest.java b/org.eclipse.xtend.core.tests/src/org/eclipse/xtend/core/tests/compiler/AbstractXbaseEvaluationTest.java index 2b275d87ba7..b95582fbd7d 100644 --- a/org.eclipse.xtend.core.tests/src/org/eclipse/xtend/core/tests/compiler/AbstractXbaseEvaluationTest.java +++ b/org.eclipse.xtend.core.tests/src/org/eclipse/xtend/core/tests/compiler/AbstractXbaseEvaluationTest.java @@ -909,9 +909,17 @@ public abstract class AbstractXbaseEvaluationTest extends Assert { } @Test public void testStringLiteral_03() throws Exception { - assertEvaluatesTo("lite\r\nr\\al", "'lite\r\nr\\\\al'"); + assertEvaluatesTo("lite\nr\\al", "'lite\r\nr\\\\al'"); } - + + @Test public void testStringLiteral_03_Issue_2293_01() throws Exception { + assertEvaluatesTo("lite\nr\\al", "'lite\\nr\\\\al'"); + } + + @Test public void testStringLiteral_03_Issue_2293_02() throws Exception { + assertEvaluatesTo("lite\r\nr\\al", "'lite\\r\\nr\\\\al'"); + } + @Test public void testStringLiteral_04() throws Exception { assertEvaluatesTo('\n', "{ val char x = '\n' x}"); } diff --git a/org.eclipse.xtend.core/src/org/eclipse/xtend/core/XtendRuntimeModule.java b/org.eclipse.xtend.core/src/org/eclipse/xtend/core/XtendRuntimeModule.java index 9db22686160..2b33da09ae7 100644 --- a/org.eclipse.xtend.core/src/org/eclipse/xtend/core/XtendRuntimeModule.java +++ b/org.eclipse.xtend.core/src/org/eclipse/xtend/core/XtendRuntimeModule.java @@ -17,7 +17,7 @@ import org.eclipse.xtend.core.compiler.XtendOutputConfigurationProvider; import org.eclipse.xtend.core.conversion.IntUnderscoreValueConverter; import org.eclipse.xtend.core.conversion.JavaIDValueConverter; -import org.eclipse.xtend.core.conversion.StringValueConverter; +import org.eclipse.xtend.core.conversion.XtendStringValueConverter; import org.eclipse.xtend.core.conversion.XtendValueConverterService; import org.eclipse.xtend.core.documentation.XtendDocumentationProvider; import org.eclipse.xtend.core.documentation.XtendFileHeaderProvider; @@ -296,8 +296,9 @@ public Class b return IntUnderscoreValueConverter.class; } + @Override public Class bindSTRINGValueConverter() { - return StringValueConverter.class; + return XtendStringValueConverter.class; } public Class bindTokenRegionProvider() { diff --git a/org.eclipse.xtend.core/src/org/eclipse/xtend/core/conversion/StringValueConverter.java b/org.eclipse.xtend.core/src/org/eclipse/xtend/core/conversion/XtendStringValueConverter.java similarity index 86% rename from org.eclipse.xtend.core/src/org/eclipse/xtend/core/conversion/StringValueConverter.java rename to org.eclipse.xtend.core/src/org/eclipse/xtend/core/conversion/XtendStringValueConverter.java index 4971ffbfde9..a56ae7ca8b2 100644 --- a/org.eclipse.xtend.core/src/org/eclipse/xtend/core/conversion/StringValueConverter.java +++ b/org.eclipse.xtend.core/src/org/eclipse/xtend/core/conversion/XtendStringValueConverter.java @@ -12,21 +12,21 @@ import org.antlr.runtime.TokenSource; import org.eclipse.xtend.core.parser.antlr.internal.FlexerFactory; -import org.eclipse.xtext.conversion.impl.STRINGValueConverter; +import org.eclipse.xtext.xbase.conversion.XbaseStringValueConverter; import com.google.inject.Inject; /** * @author Sebastian Zarnekow - Initial contribution and API */ -public class StringValueConverter extends STRINGValueConverter { +public class XtendStringValueConverter extends XbaseStringValueConverter { @Inject private FlexerFactory flexerFactory; - + @Override protected TokenSource getTokenSource(String escapedValue) { return flexerFactory.createTokenSource(new StringReader(escapedValue)); } - + } diff --git a/org.eclipse.xtext.xbase.testing/META-INF/MANIFEST.MF b/org.eclipse.xtext.xbase.testing/META-INF/MANIFEST.MF index 7c373ec4e77..2e8f07c6086 100644 --- a/org.eclipse.xtext.xbase.testing/META-INF/MANIFEST.MF +++ b/org.eclipse.xtext.xbase.testing/META-INF/MANIFEST.MF @@ -16,7 +16,7 @@ Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.xtext.xbase.testing;version="2.35.0", org.eclipse.xtext.xbase.testing.evaluation;version="2.35.0";x-friends:="org.eclipse.xtext.xbase.tests,org.eclipse.xtext.purexbase.tests", org.eclipse.xtext.xbase.testing.typesystem;version="2.35.0";x-internal:=true, - testdata;version="2.35.0";x-friends:="org.eclipse.xtext.xbase.tests", + testdata;version="2.35.0";x-friends:="org.eclipse.xtext.xbase.tests,org.eclipse.xtend.core.tests", testdata.a;version="2.35.0";x-internal:=true, testdata.b;version="2.35.0";x-internal:=true Import-Package: org.apache.log4j;version="1.2.24" diff --git a/org.eclipse.xtext.xbase.testing/src/org/eclipse/xtext/xbase/testing/evaluation/AbstractXbaseEvaluationTest.java b/org.eclipse.xtext.xbase.testing/src/org/eclipse/xtext/xbase/testing/evaluation/AbstractXbaseEvaluationTest.java index 4525cf7f404..09a3920de39 100644 --- a/org.eclipse.xtext.xbase.testing/src/org/eclipse/xtext/xbase/testing/evaluation/AbstractXbaseEvaluationTest.java +++ b/org.eclipse.xtext.xbase.testing/src/org/eclipse/xtext/xbase/testing/evaluation/AbstractXbaseEvaluationTest.java @@ -912,9 +912,17 @@ public abstract class AbstractXbaseEvaluationTest extends Assert { } @Test public void testStringLiteral_03() throws Exception { - assertEvaluatesTo("lite\r\nr\\al", "'lite\r\nr\\\\al'"); + assertEvaluatesTo("lite\nr\\al", "'lite\r\nr\\\\al'"); } - + + @Test public void testStringLiteral_03_Issue_2293_01() throws Exception { + assertEvaluatesTo("lite\nr\\al", "'lite\\nr\\\\al'"); + } + + @Test public void testStringLiteral_03_Issue_2293_02() throws Exception { + assertEvaluatesTo("lite\r\nr\\al", "'lite\\r\\nr\\\\al'"); + } + @Test public void testStringLiteral_04() throws Exception { assertEvaluatesTo('\n', "{ val char x = '\n' x}"); } diff --git a/org.eclipse.xtext.xbase.tests/src/org/eclipse/xtext/xbase/tests/compiler/Compiler2Tests.java b/org.eclipse.xtext.xbase.tests/src/org/eclipse/xtext/xbase/tests/compiler/Compiler2Tests.java index 29d87be885c..d63c335fd6f 100644 --- a/org.eclipse.xtext.xbase.tests/src/org/eclipse/xtext/xbase/tests/compiler/Compiler2Tests.java +++ b/org.eclipse.xtext.xbase.tests/src/org/eclipse/xtext/xbase/tests/compiler/Compiler2Tests.java @@ -2190,4 +2190,39 @@ public void testLibIssue60() throws Exception { "}\n" + "return _xblockexpression;\n"); } + + @Test + public void testStringLiteralWithUnixEOL_Issue2293() throws Exception { + compilesTo( + "{var s = \"a multiline\nstring\"}", + "String s = \"a multiline\\nstring\";"); + } + + @Test + public void testStringLiteralWithWindowsEOL_Issue2293() throws Exception { + compilesTo( + "{var s = \"a multiline\r\nstring\r\nstring\"}", + "String s = \"a multiline\\nstring\\nstring\";"); + } + + @Test + public void testStringLiteralWithCarriageReturn_Issue2293() throws Exception { + compilesTo( + "{\"astring\".toString.replace(\"\\r\", \"\");}", + "return \"astring\".toString().replace(\"\\r\", \"\");"); + } + + @Test + public void testStringLiteralWithCarriageReturn2_Issue2293() throws Exception { + compilesTo( + "{\"astring\".toString.replaceAll(\"\\r?\\n\", \"\\n\");}", + "return \"astring\".toString().replaceAll(\"\\r?\\n\", \"\\n\");"); + } + + @Test + public void testStringLiteralWithCarriageReturn3_Issue2293() throws Exception { + compilesTo( + "{\"astring\".toString.replaceAll(\"\\r\\n\", \"\\n\");}", + "return \"astring\".toString().replaceAll(\"\\r\\n\", \"\\n\");"); + } } diff --git a/org.eclipse.xtext.xbase/src/org/eclipse/xtext/xbase/DefaultXbaseRuntimeModule.java b/org.eclipse.xtext.xbase/src/org/eclipse/xtext/xbase/DefaultXbaseRuntimeModule.java index 3e4c35f1c68..ae5e594c770 100644 --- a/org.eclipse.xtext.xbase/src/org/eclipse/xtext/xbase/DefaultXbaseRuntimeModule.java +++ b/org.eclipse.xtext.xbase/src/org/eclipse/xtext/xbase/DefaultXbaseRuntimeModule.java @@ -10,6 +10,7 @@ import org.eclipse.xtext.common.types.DefaultCommonTypesRuntimeModule; import org.eclipse.xtext.conversion.IValueConverterService; +import org.eclipse.xtext.conversion.impl.STRINGValueConverter; import org.eclipse.xtext.debug.IStratumBreakpointSupport; import org.eclipse.xtext.documentation.IJavaDocTypeReferenceProvider; import org.eclipse.xtext.findReferences.TargetURICollector; @@ -39,6 +40,7 @@ import org.eclipse.xtext.xbase.annotations.validation.UnresolvedFeatureCallTypeAwareMessageProvider; import org.eclipse.xtext.xbase.compiler.JvmModelGenerator; import org.eclipse.xtext.xbase.compiler.output.TraceAwarePostProcessor; +import org.eclipse.xtext.xbase.conversion.XbaseStringValueConverter; import org.eclipse.xtext.xbase.conversion.XbaseValueConverterService; import org.eclipse.xtext.xbase.debug.XbaseStratumBreakpointSupport; import org.eclipse.xtext.xbase.featurecalls.IdentifiableSimpleNameProvider; @@ -242,5 +244,11 @@ public Class bindTargetURICollector() { public Class bindIJavaDocReferenceProvider() { return XbaseJavaDocTypeReferenceProvider.class; } - + + /** + * @since 2.35 + */ + public Class bindSTRINGValueConverter() { + return XbaseStringValueConverter.class; + } } diff --git a/org.eclipse.xtext.xbase/src/org/eclipse/xtext/xbase/conversion/XbaseStringValueConverter.java b/org.eclipse.xtext.xbase/src/org/eclipse/xtext/xbase/conversion/XbaseStringValueConverter.java new file mode 100644 index 00000000000..fd91de3c5ec --- /dev/null +++ b/org.eclipse.xtext.xbase/src/org/eclipse/xtext/xbase/conversion/XbaseStringValueConverter.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2024 Lorenzo Bettini and others. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.xtext.xbase.conversion; + +import org.eclipse.xtext.conversion.impl.STRINGValueConverter; +import org.eclipse.xtext.nodemodel.INode; +import org.eclipse.xtext.util.Strings; + +/** + * Avoid Windows EOL characters from the original parsed text: this would result + * in different generated Java files in Windows see + * https://github.com/eclipse/xtext/issues/2293 This is aligned with Java text + * blocks' "Normalization of Line Terminators" + * + * @author Lorenzo Bettini - Initial contribution and API + * @since 2.35 + */ +public class XbaseStringValueConverter extends STRINGValueConverter { + @Override + public String toValue(String string, INode node) { + return super.toValue(Strings.toUnixLineSeparator(string), node); + } +} diff --git a/org.eclipse.xtext.xbase/src/org/eclipse/xtext/xbase/conversion/XbaseValueConverterService.java b/org.eclipse.xtext.xbase/src/org/eclipse/xtext/xbase/conversion/XbaseValueConverterService.java index b4acf20fc2e..1fbe3915b19 100644 --- a/org.eclipse.xtext.xbase/src/org/eclipse/xtext/xbase/conversion/XbaseValueConverterService.java +++ b/org.eclipse.xtext.xbase/src/org/eclipse/xtext/xbase/conversion/XbaseValueConverterService.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 itemis AG (http://www.itemis.eu) and others. + * Copyright (c) 2011, 2024 itemis AG (http://www.itemis.eu) and others. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. @@ -34,6 +34,8 @@ *

Clients, who extend Xbase should inherit from this value converter service.

* * @author Sebastian Zarnekow - Initial contribution and API + * @author Lorenzo Bettini - remove Windows EOLs from string literals, + * https://github.com/eclipse/xtext/issues/2293 */ @Singleton public class XbaseValueConverterService extends DefaultTerminalConverters { @@ -251,4 +253,5 @@ public Integer toValue(String string, INode node) { return super.toValue(withoutUnderscore, node); } } + }