diff --git a/org.eclipse.xtext.xbase.tests/src/org/eclipse/xtext/xbase/tests/validation/JvmGenericTypeValidatorTest.java b/org.eclipse.xtext.xbase.tests/src/org/eclipse/xtext/xbase/tests/validation/JvmGenericTypeValidatorTest.java index 0e6c7ccae28..1788f349580 100644 --- a/org.eclipse.xtext.xbase.tests/src/org/eclipse/xtext/xbase/tests/validation/JvmGenericTypeValidatorTest.java +++ b/org.eclipse.xtext.xbase.tests/src/org/eclipse/xtext/xbase/tests/validation/JvmGenericTypeValidatorTest.java @@ -476,6 +476,39 @@ public void testWildcardSuperType() throws Exception { "reduce", "visibility"); } + @Test public void testIncompatibleThrowsClause() throws Exception { + var source = "class Foo extends test.ExceptionThrowing {" + + "def void ioException() throws Exception {} }"; + var model = parse(source); + validationHelper.assertError(model, MY_METHOD, INCOMPATIBLE_THROWS_CLAUSE, + source.lastIndexOf("Exception"), "Exception".length(), + "Exception", "is not", "compatible", "throws", "clause"); + } + + /** + * Two incompatible exceptions from three supertypes; + * the marker is set on the offending exceptions only. + * https://github.com/eclipse/xtext/issues/2912 + */ + @Test public void testIncompatibleThrowsClauseFromMultipleSuperTypes() throws Exception { + var source = "class Foo extends test.ExceptionThrowing " + + "implements test.ExceptionThrowingInterface, test.ExceptionThrowingInterface2 {" + + "def void nullPointerException() throws " + + "NullPointerException, java.io.IOException, java.io.FileNotFoundException {} " + + "}"; + var model = parse(source); + var expectedSuffix = " is not compatible with the throws clause in " + + "ExceptionThrowing.nullPointerException(), ExceptionThrowingInterface.nullPointerException() and ExceptionThrowingInterface2.nullPointerException()"; + validationHelper.assertError(model, MY_METHOD, INCOMPATIBLE_THROWS_CLAUSE, + source.indexOf("java.io.IOException"), "java.io.IOException".length(), + "declared exception IOException", + expectedSuffix); + validationHelper.assertError(model, MY_METHOD, INCOMPATIBLE_THROWS_CLAUSE, + source.indexOf("java.io.FileNotFoundException"), "java.io.FileNotFoundException".length(), + "declared exception FileNotFoundException", + expectedSuffix); + } + @Test public void testDuplicateParameter() throws Exception { var source = "class Foo { def void foo(int x, int x) {} }"; var model = parse(source); diff --git a/org.eclipse.xtext.xbase.tests/testdata/test/ExceptionThrowing.java b/org.eclipse.xtext.xbase.tests/testdata/test/ExceptionThrowing.java new file mode 100644 index 00000000000..71b7e433897 --- /dev/null +++ b/org.eclipse.xtext.xbase.tests/testdata/test/ExceptionThrowing.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 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. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package test; + +import java.io.IOException; + +/** + * @author Lorenzo Bettini - Initial contribution and API + */ +public class ExceptionThrowing { + + public void ioException() throws IOException { + } + + public void nullPointerException() throws NullPointerException { + } + +} diff --git a/org.eclipse.xtext.xbase.tests/testdata/test/ExceptionThrowingInterface.java b/org.eclipse.xtext.xbase.tests/testdata/test/ExceptionThrowingInterface.java new file mode 100644 index 00000000000..57c1bd311f3 --- /dev/null +++ b/org.eclipse.xtext.xbase.tests/testdata/test/ExceptionThrowingInterface.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 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. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package test; + +/** + * @author Lorenzo Bettini - Initial contribution and API + */ +interface ExceptionThrowingInterface { + + void nullPointerException() throws NullPointerException; +} diff --git a/org.eclipse.xtext.xbase.tests/testdata/test/ExceptionThrowingInterface2.java b/org.eclipse.xtext.xbase.tests/testdata/test/ExceptionThrowingInterface2.java new file mode 100644 index 00000000000..d196f80e4a3 --- /dev/null +++ b/org.eclipse.xtext.xbase.tests/testdata/test/ExceptionThrowingInterface2.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 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. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package test; + +/** + * @author Lorenzo Bettini - Initial contribution and API + */ +interface ExceptionThrowingInterface2 { + + void nullPointerException() throws NullPointerException; + +}