Permalink
Browse files

Fixed #1000594. No longer report incorrect _missing implementation me…

…thod_ error on Java classes that inherit non-deferred traits' members by subclassing a Scala abstract class
  • Loading branch information...
2 parents b74fa90 + 9446417 commit d34fdfc0892325c6aa8bb45a85af248cba9f7fd9 @dotta dotta committed Sep 15, 2011
Showing with 445 additions and 4 deletions.
  1. +1 −0 org.scala-ide.sdt.aspects/META-INF/MANIFEST.MF
  2. +1 −0 org.scala-ide.sdt.aspects/META-INF/aop.xml
  3. +70 −0 org.scala-ide.sdt.aspects/methodVerifier.exsd
  4. +1 −0 org.scala-ide.sdt.aspects/plugin.xml
  5. +8 −0 ...t.aspects/src/scala/tools/eclipse/contribution/weaving/jdt/jcompiler/IMethodVerifierProvider.java
  6. +42 −0 ...de.sdt.aspects/src/scala/tools/eclipse/contribution/weaving/jdt/jcompiler/MethodVerifierAspect.aj
  7. +19 −0 ...ts/src/scala/tools/eclipse/contribution/weaving/jdt/jcompiler/MethodVerifierProviderRegistry.java
  8. +4 −2 org.scala-ide.sdt.core.tests/src/scala/tools/eclipse/TestsSuite.java
  9. +74 −0 org.scala-ide.sdt.core.tests/src/scala/tools/eclipse/jcompiler/AbstractMethodVerifierTest.scala
  10. +7 −0 org.scala-ide.sdt.core.tests/test-workspace/jcompiler/.classpath
  11. +18 −0 org.scala-ide.sdt.core.tests/test-workspace/jcompiler/.project
  12. +7 −0 org.scala-ide.sdt.core.tests/test-workspace/jcompiler/src/t1000594_neg/A.scala
  13. +4 −0 org.scala-ide.sdt.core.tests/test-workspace/jcompiler/src/t1000594_neg/C.java
  14. +22 −0 org.scala-ide.sdt.core.tests/test-workspace/jcompiler/src/t1000594_pos/A.scala
  15. +7 −0 org.scala-ide.sdt.core.tests/test-workspace/jcompiler/src/t1000594_pos/C.java
  16. +2 −0 org.scala-ide.sdt.core/META-INF/MANIFEST.MF
  17. +4 −0 org.scala-ide.sdt.core/plugin.xml
  18. +148 −0 org.scala-ide.sdt.core/src/scala/tools/eclipse/jcompiler/ScalaMethodVerifierProvider.scala
  19. +6 −2 org.scala-ide.sdt.core/src/scala/tools/eclipse/util/Logger.scala
@@ -39,6 +39,7 @@ Export-Package:
scala.tools.eclipse.contribution.weaving.jdt.debug,
scala.tools.eclipse.contribution.weaving.jdt.hierarchy,
scala.tools.eclipse.contribution.weaving.jdt.indexerprovider,
+ scala.tools.eclipse.contribution.weaving.jdt.jcompiler,
scala.tools.eclipse.contribution.weaving.jdt.launching,
scala.tools.eclipse.contribution.weaving.jdt.search,
scala.tools.eclipse.contribution.weaving.jdt.spellingengineprovider,
@@ -12,6 +12,7 @@
<aspect name="scala.tools.eclipse.contribution.weaving.jdt.core.SourceLookupAspect"/>
<aspect name="scala.tools.eclipse.contribution.weaving.jdt.hierarchy.HierarchyAspect"/>
<aspect name="scala.tools.eclipse.contribution.weaving.jdt.indexerprovider.IndexerProviderAspect"/>
+<aspect name="scala.tools.eclipse.contribution.weaving.jdt.jcompiler.MethodVerifierAspect"/>
<aspect name="scala.tools.eclipse.contribution.weaving.jdt.launching.JavaLaunchableTesterAspect"/>
<aspect name="scala.tools.eclipse.contribution.weaving.jdt.search.SearchAspect"/>
<aspect name="scala.tools.eclipse.contribution.weaving.jdt.ui.ScalaOverrideLabelAspect"/>
@@ -0,0 +1,70 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="scala.tools.eclipse.contribution.weaving.jdt" xmlns="http://www.w3.org/2001/XMLSchema">
+ <annotation>
+ <appinfo>
+ <meta.schema plugin="scala.tools.eclipse.contribution.weaving.jdt" id="method_verifier" name="Method Verifier"/>
+ </appinfo>
+ <documentation>
+ Provides an alternate implementation of org.eclipse.jdt.internal.compiler.lookup.MethodVerifier based on the type's owner of the verified method.
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <annotation>
+ <appinfo>
+ <meta.element />
+ </appinfo>
+ </annotation>
+ <complexType>
+ <sequence minOccurs="1" maxOccurs="unbounded">
+ <element ref="provider"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appinfo>
+ <meta.attribute translatable="true"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="provider">
+ <annotation>
+ <documentation>
+ Declares the class of the compilation unit provider for compilation units with a given file extension.
+ </documentation>
+ </annotation>
+ <complexType>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="java" basedOn=":scala.tools.eclipse.contribution.weaving.jdt.compiler.IMethodVerifierProvider"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+</schema>
@@ -5,4 +5,5 @@
<extension-point id="cfprovider" name="ClassFile Provider" schema="cfprovider.exsd"/>
<extension-point id="indexerprovider" name="Indexer Provider" schema="indexerprovider.exsd"/>
<extension-point id="formatterCleanUp" name="Formatter Clean Up" schema="formatterCleanUp.exsd"/>
+ <extension-point id="method_verifier" name="Method Verifier" schema="methodVerifier.exsd"/>
</plugin>
@@ -0,0 +1,8 @@
+package scala.tools.eclipse.contribution.weaving.jdt.jcompiler;
+
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+
+@SuppressWarnings("restriction")
+public interface IMethodVerifierProvider {
+ boolean isNotDeferredTraitMethod(MethodBinding abstractMethod);
+}
@@ -0,0 +1,42 @@
+package scala.tools.eclipse.contribution.weaving.jdt.jcompiler;
+
+import java.util.List;
+
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.MethodVerifier;
+
+@SuppressWarnings("restriction")
+public aspect MethodVerifierAspect {
+
+ pointcut checkAbstractMethod(MethodVerifier methodVerifier,
+ MethodBinding abstractMethod):
+ execution(void MethodVerifier+.checkAbstractMethod(MethodBinding)) &&
+ args(abstractMethod) &&
+ this(methodVerifier);
+
+ void around(MethodVerifier methodVerifier, MethodBinding abstractMethod):
+ checkAbstractMethod(methodVerifier, abstractMethod) {
+ List<IMethodVerifierProvider> providers = MethodVerifierProviderRegistry
+ .getInstance().getProviders();
+
+ if (providers.isEmpty()) {
+ proceed(methodVerifier, abstractMethod);
+ return;
+ }
+
+ if (providers.size() > 1) {
+ throw new IllegalStateException(
+ "Exactly one provider is expected for extension '"
+ + MethodVerifierProviderRegistry.METHOD_VERIFIER_PROVIDERS_EXTENSION_POINT
+ + "'. Found " + providers.size());
+ }
+
+ IMethodVerifierProvider provider = providers.get(0);
+
+ if (provider.isNotDeferredTraitMethod(abstractMethod))
+ // stop the abstract method's check if the method is a non-deferred (i.e. concrete) trait method
+ return;
+ else
+ proceed(methodVerifier, abstractMethod);
+ }
+}
@@ -0,0 +1,19 @@
+package scala.tools.eclipse.contribution.weaving.jdt.jcompiler;
+
+import scala.tools.eclipse.contribution.weaving.jdt.util.AbstractProviderRegistry;
+
+public class MethodVerifierProviderRegistry extends
+ AbstractProviderRegistry<IMethodVerifierProvider> {
+ private static final MethodVerifierProviderRegistry INSTANCE = new MethodVerifierProviderRegistry();
+
+ public static String METHOD_VERIFIER_PROVIDERS_EXTENSION_POINT = "org.scala-ide.sdt.aspects.method_verifier"; //$NON-NLS-1$
+
+ public static MethodVerifierProviderRegistry getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ protected String getExtensionPointId() {
+ return METHOD_VERIFIER_PROVIDERS_EXTENSION_POINT;
+ }
+}
@@ -2,13 +2,14 @@
import scala.tools.eclipse.completion.CompletionTests;
import scala.tools.eclipse.hyperlinks.HyperlinkDetectorTests;
+import scala.tools.eclipse.jcompiler.AbstractMethodVerifierTest;
import scala.tools.eclipse.lexical.ScalaDocumentPartitionerTest;
import scala.tools.eclipse.lexical.ScalaPartitionTokeniserTest;
import scala.tools.eclipse.occurrences.OccurrencesFinderTest;
import scala.tools.eclipse.structurebuilder.StructureBuilderTest;
-import scala.tools.eclipse.ui.TestScalaIndenter;
import scala.tools.eclipse.wizards.*;
+
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@@ -26,6 +27,7 @@
HyperlinkDetectorTests.class,
OccurrencesFinderTest.class,
StructureBuilderTest.class,
- CompletionTests.class
+ CompletionTests.class,
+ AbstractMethodVerifierTest.class
})
class TestsSuite { }
@@ -0,0 +1,74 @@
+package scala.tools.eclipse.jcompiler
+
+import org.junit.Assert._
+import org.junit.Test
+import org.eclipse.jdt.internal.ui.JavaPlugin
+import org.eclipse.jface.text.source.IAnnotationModelListener
+import org.eclipse.jface.text.source.IAnnotationModel
+import scala.tools.eclipse.testsetup.TestProjectSetup
+import org.eclipse.core.resources.IncrementalProjectBuilder
+import org.eclipse.core.runtime.NullProgressMonitor
+import org.eclipse.jdt.internal.ui.viewsupport.IProblemChangedListener
+import org.eclipse.core.resources.IResource
+import org.eclipse.jdt.core.IProblemRequestor
+import org.eclipse.jdt.core.compiler.IProblem
+import org.eclipse.jdt.core.WorkingCopyOwner
+import org.eclipse.core.resources.ResourcesPlugin
+import org.eclipse.jdt.core.ICompilationUnit
+import org.eclipse.core.resources.IMarker
+import org.eclipse.jdt.core.IJavaModelMarker
+import org.mockito.Mockito._
+import org.mockito.Matchers.any
+
+object AbstractMethodVerifierTest extends TestProjectSetup("jcompiler")
+
+class AbstractMethodVerifierTest {
+ import AbstractMethodVerifierTest._
+
+ private class ProblemReporterAdapter extends IProblemRequestor {
+ def acceptProblem(problem: IProblem) {}
+ def beginReporting() {}
+ def endReporting() {}
+ def isActive(): Boolean = true
+ }
+
+ @Test
+ def t1000594_pos_ErrorsAreDisplayedInJavaEditor_If_JavaClass_IsSubtypeOf_ScalaAbstractClass_ThatInherithedFromATraitWithOnlyConcreteMembers() {
+ //when
+ val unit = compilationUnit("t1000594_pos/C.java")
+ val owner = new WorkingCopyOwner() {
+ override def getProblemRequestor(unit: org.eclipse.jdt.core.ICompilationUnit): IProblemRequestor =
+ new ProblemReporterAdapter {
+ override def acceptProblem(problem: IProblem) {
+ //verify
+ assert(false, "found problem: " + problem)
+ }
+ }
+ }
+
+ //then
+ // this will trigger the java reconciler so that the problems will be reported in the ProblemReporter
+ unit.getWorkingCopy(owner, new NullProgressMonitor)
+ }
+
+ @Test
+ def t1000594_neg_ErrorsAreDisplayedInJavaEditor_If_JavaClass_IsSubtypeOf_ScalaAbstractClass_ThatInherithedFromATraitWithOnlyConcreteMembers() {
+ //when
+ val unit = compilationUnit("t1000594_neg/C.java")
+
+ val requestor = mock(classOf[IProblemRequestor])
+ when(requestor.isActive()).thenReturn(true)
+
+ val owner = new WorkingCopyOwner() {
+ override def getProblemRequestor(unit: org.eclipse.jdt.core.ICompilationUnit): IProblemRequestor = requestor
+ }
+
+ // then
+ // this will trigger the java reconciler so that the problems will be reported to the `requestor`
+ unit.getWorkingCopy(owner, new NullProgressMonitor)
+
+ // verify
+ verify(requestor, times(1)).acceptProblem(any())
+ }
+
+}
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>jcompiler</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.scala-ide.sdt.core.scalabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.scala-ide.sdt.core.scalanature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
@@ -0,0 +1,7 @@
+package t1000594_neg
+
+trait A {
+ def foo(s: List[Option[String]]): Unit
+}
+
+abstract class B extends A
@@ -0,0 +1,4 @@
+package t1000594_neg;
+
+public class C extends B {
+}
@@ -0,0 +1,22 @@
+package t1000594_pos
+
+trait A {
+
+ def foo(n: Int) {
+ Some(n)
+ }
+
+
+ def foo(s: List[Option[String]]): Unit = {}
+
+ private def foo(n: Set[String]) {}
+
+ def foo(n: Option[String]) {}
+
+ def foo(s: String, n: Option[String]): Int => Unit = foo(s)(n) _
+
+ def foo(s: String)(n: Option[String])(n2: Int) {}
+
+}
+
+abstract class B extends A
@@ -0,0 +1,7 @@
+package t1000594_pos;
+
+public class C extends B {
+ @Override
+ public void foo(int n) {
+ }
+}
@@ -57,6 +57,7 @@ Import-Package:
scala.tools.eclipse.contribution.weaving.jdt.core;apply-aspects:=false,
scala.tools.eclipse.contribution.weaving.jdt.hierarchy;apply-aspects:=false,
scala.tools.eclipse.contribution.weaving.jdt.indexerprovider;apply-aspects:=false,
+ scala.tools.eclipse.contribution.weaving.jdt.jcompiler;apply-aspects:=false,
scala.tools.eclipse.contribution.weaving.jdt.launching;apply-aspects:=false,
scala.tools.eclipse.contribution.weaving.jdt.search;apply-aspects:=false,
scala.tools.eclipse.contribution.weaving.jdt.spellingengineprovider;apply-aspects:=false,
@@ -76,6 +77,7 @@ Export-Package:
scala.tools.eclipse.formatter,
scala.tools.eclipse.interpreter,
scala.tools.eclipse.javaelements,
+ scala.tools.eclipse.jcompiler,
scala.tools.eclipse.launching,
scala.tools.eclipse.lexical,
scala.tools.eclipse.markoccurrences,
@@ -825,6 +825,10 @@
<provider class="scala.tools.eclipse.formatter.ScalaFormatterCleanUpProvider" />
</extension>
+ <extension point="org.scala-ide.sdt.aspects.method_verifier">
+ <provider class="scala.tools.eclipse.jcompiler.ScalaMethodVerifierProvider" />
+ </extension>
+
<extension point="org.eclipse.contribution.weaving.jdt.imagedescriptorselector">
<selector
class="scala.tools.eclipse.javaelements.ScalaImageDescriptorSelector">
Oops, something went wrong.

0 comments on commit d34fdfc

Please sign in to comment.