diff --git a/org.eclipse.xtend.core.tests/src/org/eclipse/xtend/core/tests/java8/compiler/Java8Compiler2Test.xtend b/org.eclipse.xtend.core.tests/src/org/eclipse/xtend/core/tests/java8/compiler/Java8Compiler2Test.xtend index 9d288c4fdce..f90927bf76e 100644 --- a/org.eclipse.xtend.core.tests/src/org/eclipse/xtend/core/tests/java8/compiler/Java8Compiler2Test.xtend +++ b/org.eclipse.xtend.core.tests/src/org/eclipse/xtend/core/tests/java8/compiler/Java8Compiler2Test.xtend @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2020 itemis AG (http://www.itemis.eu) and others. + * Copyright (c) 2015, 2023 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. @@ -36,6 +36,30 @@ class Java8Compiler2Test extends XtendCompilerTest { ''') } + @Test def void testStaticMethodInInterface2() { + ''' + class B implements A { + def void m2(int i) { + i.substring(); + } + } + interface A { + @Extension + public static String s; + def void m1(int i) { + i.substring(); + } + } + '''.assertCompilesTo(''' + @SuppressWarnings("all") + public class B implements A { + public void m2(final int i) { + A.s.substring(i); + } + } + ''') + } + @Test override testMultiCatch_02() { assertCompilesTo(''' @@ -1576,4 +1600,35 @@ class Java8Compiler2Test extends XtendCompilerTest { ''') } -} \ No newline at end of file + @Test def void testExtensionFieldInInterface() { + ''' + package foo; + + interface Foo { + extension Bar bar = new Bar + def void someMethod(String assert) { + "".doit + } + } + + class Bar { + def void doit(String a) {} + } + '''.assertCompilesTo(''' + package foo; + + import org.eclipse.xtext.xbase.lib.Extension; + + @SuppressWarnings("all") + public interface Foo { + @Extension + static final Bar bar = new Bar(); + + default void someMethod(final String assert_) { + Foo.bar.doit(""); + } + } + ''') + } + +} diff --git a/org.eclipse.xtend.core.tests/src/org/eclipse/xtend/core/tests/java8/validation/Java8ValidationTest.xtend b/org.eclipse.xtend.core.tests/src/org/eclipse/xtend/core/tests/java8/validation/Java8ValidationTest.xtend index c27f4d57859..8e3bd728ab0 100644 --- a/org.eclipse.xtend.core.tests/src/org/eclipse/xtend/core/tests/java8/validation/Java8ValidationTest.xtend +++ b/org.eclipse.xtend.core.tests/src/org/eclipse/xtend/core/tests/java8/validation/Java8ValidationTest.xtend @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2016 itemis AG (http://www.itemis.eu) and others. + * Copyright (c) 2015, 2023 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. @@ -527,4 +527,12 @@ class Java8ValidationTest extends AbstractXtendTestCase { "The enclosing type does not extend or implement the interface List") } + @Test + def void testInterfaceExtensionField() { + file(''' + interface MyIf { + extension Integer foo + } + ''').assertNoErrors + } } diff --git a/org.eclipse.xtend.core.tests/xtend-gen/org/eclipse/xtend/core/tests/java8/compiler/Java8Compiler2Test.java b/org.eclipse.xtend.core.tests/xtend-gen/org/eclipse/xtend/core/tests/java8/compiler/Java8Compiler2Test.java index cf38cfac889..9548200adee 100644 --- a/org.eclipse.xtend.core.tests/xtend-gen/org/eclipse/xtend/core/tests/java8/compiler/Java8Compiler2Test.java +++ b/org.eclipse.xtend.core.tests/xtend-gen/org/eclipse/xtend/core/tests/java8/compiler/Java8Compiler2Test.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015, 2020 itemis AG (http://www.itemis.eu) and others. + * Copyright (c) 2015, 2023 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. @@ -55,6 +55,60 @@ public void testStaticMethodInInterface() { this.assertCompilesTo(_builder, _builder_1); } + @Test + public void testStaticMethodInInterface2() { + StringConcatenation _builder = new StringConcatenation(); + _builder.append("class B implements A {"); + _builder.newLine(); + _builder.append("\t"); + _builder.append("def void m2(int i) {"); + _builder.newLine(); + _builder.append("\t\t"); + _builder.append("i.substring();"); + _builder.newLine(); + _builder.append("\t"); + _builder.append("}"); + _builder.newLine(); + _builder.append("}"); + _builder.newLine(); + _builder.append("interface A {"); + _builder.newLine(); + _builder.append("\t"); + _builder.append("@Extension"); + _builder.newLine(); + _builder.append("\t"); + _builder.append("public static String s;"); + _builder.newLine(); + _builder.append("\t"); + _builder.append("def void m1(int i) {"); + _builder.newLine(); + _builder.append("\t\t"); + _builder.append("i.substring();"); + _builder.newLine(); + _builder.append("\t"); + _builder.append("}"); + _builder.newLine(); + _builder.append("}"); + _builder.newLine(); + StringConcatenation _builder_1 = new StringConcatenation(); + _builder_1.append("@SuppressWarnings(\"all\")"); + _builder_1.newLine(); + _builder_1.append("public class B implements A {"); + _builder_1.newLine(); + _builder_1.append(" "); + _builder_1.append("public void m2(final int i) {"); + _builder_1.newLine(); + _builder_1.append(" "); + _builder_1.append("A.s.substring(i);"); + _builder_1.newLine(); + _builder_1.append(" "); + _builder_1.append("}"); + _builder_1.newLine(); + _builder_1.append("}"); + _builder_1.newLine(); + this.assertCompilesTo(_builder, _builder_1); + } + @Test @Override public void testMultiCatch_02() { @@ -3582,4 +3636,66 @@ public void testJavaKeywordsUsed() { _builder_1.newLine(); this.assertCompilesTo(_builder, _builder_1); } + + @Test + public void testExtensionFieldInInterface() { + StringConcatenation _builder = new StringConcatenation(); + _builder.append("package foo;"); + _builder.newLine(); + _builder.newLine(); + _builder.append("interface Foo {"); + _builder.newLine(); + _builder.append("\t"); + _builder.append("extension Bar bar = new Bar"); + _builder.newLine(); + _builder.append("\t"); + _builder.append("def void someMethod(String assert) {"); + _builder.newLine(); + _builder.append("\t\t"); + _builder.append("\"\".doit"); + _builder.newLine(); + _builder.append("\t"); + _builder.append("}"); + _builder.newLine(); + _builder.append("}"); + _builder.newLine(); + _builder.newLine(); + _builder.append("class Bar {"); + _builder.newLine(); + _builder.append("\t"); + _builder.append("def void doit(String a) {}"); + _builder.newLine(); + _builder.append("}"); + _builder.newLine(); + StringConcatenation _builder_1 = new StringConcatenation(); + _builder_1.append("package foo;"); + _builder_1.newLine(); + _builder_1.newLine(); + _builder_1.append("import org.eclipse.xtext.xbase.lib.Extension;"); + _builder_1.newLine(); + _builder_1.newLine(); + _builder_1.append("@SuppressWarnings(\"all\")"); + _builder_1.newLine(); + _builder_1.append("public interface Foo {"); + _builder_1.newLine(); + _builder_1.append(" "); + _builder_1.append("@Extension"); + _builder_1.newLine(); + _builder_1.append(" "); + _builder_1.append("static final Bar bar = new Bar();"); + _builder_1.newLine(); + _builder_1.newLine(); + _builder_1.append(" "); + _builder_1.append("default void someMethod(final String assert_) {"); + _builder_1.newLine(); + _builder_1.append(" "); + _builder_1.append("Foo.bar.doit(\"\");"); + _builder_1.newLine(); + _builder_1.append(" "); + _builder_1.append("}"); + _builder_1.newLine(); + _builder_1.append("}"); + _builder_1.newLine(); + this.assertCompilesTo(_builder, _builder_1); + } } diff --git a/org.eclipse.xtend.core.tests/xtend-gen/org/eclipse/xtend/core/tests/java8/validation/Java8ValidationTest.java b/org.eclipse.xtend.core.tests/xtend-gen/org/eclipse/xtend/core/tests/java8/validation/Java8ValidationTest.java index f2b49575b94..72f57ab2afb 100644 --- a/org.eclipse.xtend.core.tests/xtend-gen/org/eclipse/xtend/core/tests/java8/validation/Java8ValidationTest.java +++ b/org.eclipse.xtend.core.tests/xtend-gen/org/eclipse/xtend/core/tests/java8/validation/Java8ValidationTest.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015, 2016 itemis AG (http://www.itemis.eu) and others. + * Copyright (c) 2015, 2023 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. @@ -1005,4 +1005,21 @@ public void testInterfaceSuperCall() { throw Exceptions.sneakyThrow(_e); } } + + @Test + public void testInterfaceExtensionField() { + try { + StringConcatenation _builder = new StringConcatenation(); + _builder.append("interface MyIf {"); + _builder.newLine(); + _builder.append("\t"); + _builder.append("extension Integer foo"); + _builder.newLine(); + _builder.append("}"); + _builder.newLine(); + this._validationTestHelper.assertNoErrors(this.file(_builder.toString())); + } catch (Throwable _e) { + throw Exceptions.sneakyThrow(_e); + } + } } diff --git a/org.eclipse.xtend.core/src/org/eclipse/xtend/core/validation/XtendValidator.java b/org.eclipse.xtend.core/src/org/eclipse/xtend/core/validation/XtendValidator.java index 56ac53702d9..a36c417ae65 100644 --- a/org.eclipse.xtend.core/src/org/eclipse/xtend/core/validation/XtendValidator.java +++ b/org.eclipse.xtend.core/src/org/eclipse/xtend/core/validation/XtendValidator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2018 itemis AG (http://www.itemis.eu) and others. + * Copyright (c) 2011, 2023 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. @@ -282,9 +282,13 @@ protected GeneratorConfig getGeneratorConfig(EObject element) { if (result.getJavaSourceVersion().isAtLeast(JAVA8)) { methodInInterfaceModifierValidator = new ModifierValidator( newArrayList("public", "abstract", "static", "def", "override"), this); + fieldInInterfaceModifierValidator = new ModifierValidator( + newArrayList("public", "static", "final", "val", "extension"), this); } else { methodInInterfaceModifierValidator = new ModifierValidator( newArrayList("public", "abstract", "def", "override"), this); + fieldInInterfaceModifierValidator = new ModifierValidator( + newArrayList("public", "static", "final", "val"), this); } } return result; @@ -2005,9 +2009,6 @@ protected boolean hasAnnotation(Iterable annotations, Cla private final ModifierValidator fieldModifierValidator = new ModifierValidator( newArrayList("public", "protected", "package", "private", "static", "final", "val", "var", "extension", "volatile", "transient"), this); - private final ModifierValidator fieldInInterfaceModifierValidator = new ModifierValidator( - newArrayList("public", "static", "final", "val"), this); - private final ModifierValidator constructorModifierValidator = new ModifierValidator( newArrayList(visibilityModifers), this); @@ -2015,6 +2016,8 @@ protected boolean hasAnnotation(Iterable annotations, Cla newArrayList("public", "protected", "package", "private", "static", "abstract", "dispatch", "final", "def", "override", "strictfp", "native", "synchronized"), this); private ModifierValidator methodInInterfaceModifierValidator; + + private ModifierValidator fieldInInterfaceModifierValidator; @Check protected void checkModifiers(XtendClass xtendClass) { diff --git a/org.eclipse.xtext.xbase/src/org/eclipse/xtext/xbase/typesystem/internal/LogicalContainerAwareReentrantTypeResolver.java b/org.eclipse.xtext.xbase/src/org/eclipse/xtext/xbase/typesystem/internal/LogicalContainerAwareReentrantTypeResolver.java index 9376adb89df..2adc9d888c3 100644 --- a/org.eclipse.xtext.xbase/src/org/eclipse/xtext/xbase/typesystem/internal/LogicalContainerAwareReentrantTypeResolver.java +++ b/org.eclipse.xtext.xbase/src/org/eclipse/xtext/xbase/typesystem/internal/LogicalContainerAwareReentrantTypeResolver.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 itemis AG (http://www.itemis.eu) and others. + * Copyright (c) 2012, 2023 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. @@ -1011,10 +1011,12 @@ protected IFeatureScopeSession addExtensionFieldsToMemberSession( } } // traverse the type hierarchy to create the feature scope sessions - JvmTypeReference superType = getExtendedClass(type); IFeatureScopeSession result = featureScopeSession; - if (superType != null) { - result = addExtensionFieldsToMemberSession(resolvedTypes, featureScopeSession, (JvmDeclaredType) superType.getType(), thisFeature, seenNames, seenTypes); + for (JvmTypeReference st : type.getSuperTypes()) { + JvmType candidateType = st.getType(); + if (candidateType instanceof JvmGenericType) { + result = addExtensionFieldsToMemberSession(resolvedTypes, featureScopeSession, (JvmDeclaredType) candidateType, thisFeature, seenNames, seenTypes); + } } if (extensionProviders != null) { result = result.addToExtensionScope(extensionProviders);