Document API Changes between releases of the IntelliJ Platform

Answered

Whenever you put out a new minor release of Idea, there are typically API changes in classes that my plugin depends on.  My plugin then fails to compile in a bunch of places, and it is tedious to try to guess what changed and how to use the new API.

Can you please supply us with a complete set of API changes for each release, with an explanation of what changed, and how to adapt our code so it continues to compile and work?

There seems to be a document you put out with API changes, but it is not exhaustive. It looks to us as though things are added to that document as plugin writers discover them.

At the moment, we are dealing with 2019.2 to 2019.3.

14 comments
Comment actions Permalink

An example API that changed: org.jetbrains.jps.cmdline.ProjectDescriptor (the constructor).

0
Comment actions Permalink

I can second the motion but realize that it is difficult to ensure without some automation to enforce it.

I would settle for having a @since java doc annotation for newly added or changed APIs with a minimum build number for its appearance

@Deprecated annotations are good but I cannot update my API use until the oldest supported IDE version is the one with the new API implementation and there is an alternative API available to implement the same functionality.

it would also be a good policy to not mark an interface/class/method @Deprecated until all the APIs that mandate its use have alternative methods for the replacement. Example: com.intellij.util.Producer is deprecated in favour of Supplier but EditorTextInsertHandler interface only has one method and it uses Producer. This deprecation is kind of pointless and generates distracting compiler warnings.

More information in the code on the min build when the change was implemented would help a lot. Right now it is a tedious search through annotations to figure out when the new API came to be and what min build is required to use it.

Sometimes the changes are in Util classes and if there is too much code depending on it on my side, the only easy solution for backward compatibility is to copy the old version into my own code until I can migrate to the new API.

Overall, this upkeep activity is time consuming and I dread doing it for major and sometimes minor IDE releases.

Don't get me wrong. I love the improvements in the IDE. I just hate the extra work it generates for me on the plugin maintenance side.

0
Comment actions Permalink

Several points to add:

  1. Deprecations can help identify which APIs to modify or stop using, in advance, provided that (as Vladimir said) the alternative exists already.  
  2. When something is deprecated, and the developer navigates to the @Deprecated statement, please consistently place JavaDoc that describes what got changed, how to adapt to it, and an explanation of why the change was made.  For example, you can say "The project parameter was added to the class constructor to improve performance."  If it is too complicated for a JavaDoc comment, link to online documentation that describes the change.
  3. I agree again with Vladimir that automation would be needed to deal with documenting all API changes.  My company has tests that use the APIs we document, and if we change them, the tests fail.  We then document the changes based on the API test failures.  
  4. Changes in Util classes are particularly tedious.  Another change I've noticed is deprecating a base class and moving those methods to a derived class, or vice versa.  I understand these have a purpose, but often cannot tell what is going on.  Again, some comments in the deprecated code would help.
0
Comment actions Permalink

BGoldberg and Vladimir, Thanks a lot for your feedback.

Regarding "org.jetbrains.jps.cmdline.ProjectDescriptor (the constructor)" - it will be fixed.
Regarding "com.intellij.util.Producer is deprecated in favour of Supplier but EditorTextInsertHandler interface only has one method and it uses Producer" - fixed.

Regarding documentation of API Changes: you're probably referring to http://www.jetbrains.org/intellij/sdk/docs/reference_guide/api_changes_list.html and http://www.jetbrains.org/intellij/sdk/docs/reference_guide/api_notable/api_notable.html. These are indeed not exhaustive in the sense we do not list every single signature change of IntelliJ Platform and bundled plugins. Is that what you are looking for, something like a full diff?

We do use tooling in our development process as well as on the plugin repository to catch binary incompatibilies (https://blog.jetbrains.com/platform/2018/07/plugins-repository-now-integrates-with-the-plugin-verification-tool/). If your plugin is _not_ published on our plugin repository, please use https://github.com/JetBrains/intellij-plugin-verifier to verify compatibility locally.

We strive to have documentation for deprecated API explaining the reasoning/alternatives, if there are missing/unclear places please feel free to ping me on the Marketplace Slack or file a bug.

If you find any breaking or confusing changes in our API, please reach out to us ASAP so we can fix/document them early in the EAP cycle, thanks in advance.

 

0
Comment actions Permalink

Yann,

We don't want to limit code improvements or changes you guys make. We just want to be able to figure out reasonably quickly how to adjust our code for the changes and if they are major have a bit of a heads up warning it is coming.

I am sure you guys have tooling to help. Any chance the tool(s) keep track of binary incompatibilities caused by changes in the API from build to build?

I know tracking API changes is a daunting task. I personally would not want a telephone book printout of all changes. Instead what I would like is a fairly quick answer as to what build or version of the IDE the changes were made for a particular API method or class. If the change is major, a brief pointer where to look for implementing equivalent functionality.

I wind up doing this search using annotations and show vcs history up to revision. Which is great, but may require some effort to figure out when exactly the change was made. At which point I have a date of the change but no idea which build it was merged into, unless I search up in git history looking for a tag. I even considered writing a plugin to help me do it.

It would also help to know of major upcoming changes in earlier phases. Many times, including latest Beta, breaking changes went into Beta or RC releases with no hint of these changes in the EAP releases.

I was under the mistaken impression that later releases stabilize and fix bugs, with major shifts in the API or the way it functions to be seen in the EAP releases. I am giving up on that illusion and taking on the attitude that when you guys make a released I will figure what it breaks in my plugin then fix it when I can.

I love your products. They are the best IDEs I have used and I refuse to work without them. I wish we can figure out how to translate this amazing user experience into a similar experience as an active plugin developer.

0
Comment actions Permalink

Hi Yann,

Could the plugin verifier be adapted to help with this? The plugin verifier (as the name suggests) is for checking plugins, but what's really needed for these problems is something for the IDE itself.

It seems like this is something that might not be too hard - basically between the binary class files of two versions of the IDE, provide a list of the function signatures that have changed. I suspect a list of all those function signature changes would not be too large, especially if you remove the additive (i.e. non-breaking) changes from the list. It should then be possible to (either manually or automatically) check that each change has some doc explaining how to adapt to the change.

Of course, this wouldn't catch cases where the API is the same but the semantics have changed. My recent example of this was https://youtrack.jetbrains.com/issue/IDEA-225412. Here the existing API was maintained and marked deprecated, but it stopped working. Additionally, the deprecation notice indicated a solution that is not what clients of the API within IntelliJ itself used. And on top of all that the new API is marked experimental, so I have a choice of receiving warnings about using a deprecated API or warnings about using an experimental one.

0
Comment actions Permalink

However, the big problem I still see is that the verifier merely tells me what is wrong, and doesn't document what I need to do to fix it, or why the semantics/API changed.  What my company does for our APIs to solve this problem is to maintain an API Diffs File, shipped along with the product, and referenced by API verifier.  If the API verifier discovers a change for which there is no entry in the API Diffs File, it reports that problem so that an entry can be made.  The API Diffs File then becomes the basis of user documentation.  The API Diffs File is shipped along with the product, along with the plugin-verifier, so that a meaningful report can be produced by the plugin-verifier.

Can you do something similar?

0
Comment actions Permalink

Below, please see the results of running your intellij-plugin-verfier on one of our plugins (for Gosu), and how it doesn't tell us how to fix the problem, only that there is a problem.  The remaining work of fixing the problems is tedious and time consuming.  If the verifier were to look in the API Diffs File proposed above, it could then explain (for each problem) what changed and how to fix it.

----------------- output ----------------

Verification reports directory: verification-2019-11-11 at 16.29.20

2019-11-11T16:29:20 [main] INFO  verification - Reading IDE /Applications/IntelliJ IDEA 2019.3 CE EAP.app/Contents

2019-11-11T16:29:22 [main] INFO  verification - Reading plugin to check from ./ij-gosu

2019-11-11T16:29:22 [main] INFO  verification - Task check-plugin parameters:

JDK              : /Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home

IDEs             : [IC-193.4932.9]

Plugins (1): [gw.gosu.ij:h-latest-user-rberlin-ISSTUDIO-527-SNAPSHOT]

Ignored : []

2019-11-11T16:29:29 [main] INFO  verification - Finished 1 of 1 verifications: IC-193.4932.9 against gw.gosu.ij:h-latest-user-rberlin-ISSTUDIO-527-SNAPSHOT: Found 43 compatibility problems

2019-11-11T16:29:29 [main] INFO  c.j.p.repository.cache.ResourceCache - Closing the JDKCache

2019-11-11T16:29:29 [main] INFO  c.j.p.repository.cache.ResourceCache - Closing the PluginDetailsCache

Against IC-193.4932.9 the plugin gw.gosu.ij:h-latest-user-rberlin-ISSTUDIO-527-SNAPSHOT has 43 problems

    #Invocation of unresolved method com.intellij.psi.statistics.StatisticsInfo.incUseCount() : void

        Method gw.gosu.ij.psi.statistics.GosuStatisticsManager.incVariableNameUseCount(java.lang.String name, com.intellij.psi.codeStyle.VariableKind variableKind, java.lang.String propertyName, gw.gosu.ij.psi.GosuPsiType type) : void contains an *invokevirtual* instruction referencing an unresolved method com.intellij.psi.statistics.StatisticsInfo.incUseCount() : void. This can lead to **NoSuchMethodError** exception at runtime.

    #Illegal access to package-private class com.intellij.util.containers.ConcurrentWeakHashMap

        Package-private class com.intellij.util.containers.ConcurrentWeakHashMap is not available at gw.gosu.ij.psi.infos.GosuMethodCandidateInfo.inferTypeArguments(GosuParameterTypeInferencePolicy project, GosuPsiExpression[] gosuPsiFacade, boolean containingClass) : GosuPsiSubstitutor. This can lead to **IllegalAccessError** exception at runtime.

        Package-private class com.intellij.util.containers.ConcurrentWeakHashMap is not available at gw.gosu.ij.codeInsight.daemon.impl.quickfix.CreateConstructorParameterFromFieldFix.getFieldsToFix() : Collection. This can lead to **IllegalAccessError** exception at runtime.

        Package-private class com.intellij.util.containers.ConcurrentWeakHashMap is not available at gw.gosu.ij.codeInsight.daemon.impl.quickfix.VariableAccessFromInnerClassFix.getVariablesToFix() : Collection. This can lead to **IllegalAccessError** exception at runtime.

        Package-private class com.intellij.util.containers.ConcurrentWeakHashMap is not available at gw.gosu.ij.psi.controlFlow.GosuControlFlowFactory.<init>(PsiManagerEx psiManager). This can lead to **IllegalAccessError** exception at runtime.

    #Invocation of unresolved method gw.gosu.ij.codeInsight.daemon.impl.GosuMarkerType.SubclassUpdater.getTheOnlyOneElement() : PsiElement

        Method gw.gosu.ij.codeInsight.daemon.impl.GosuMarkerType.SubclassUpdater.onFinished() : void contains an *invokevirtual* instruction referencing an unresolved method gw.gosu.ij.codeInsight.daemon.impl.GosuMarkerType.SubclassUpdater.getTheOnlyOneElement() : com.intellij.psi.PsiElement. This can lead to **NoSuchMethodError** exception at runtime.

The method might have been declared in the super classes or in the super interfaces:

  com.intellij.codeInsight.navigation.BackgroundUpdaterTask

  com.intellij.codeInsight.navigation.BackgroundUpdaterTaskBase

  com.intellij.codeInsight.navigation.ListBackgroundUpdaterTask

  com.intellij.openapi.progress.Task

  com.intellij.openapi.progress.Task.Backgroundable

  com.intellij.openapi.progress.PerformInBackgroundOption

  com.intellij.openapi.progress.Progressive

  com.intellij.openapi.progress.TaskInfo

    #Illegal invocation of private constructor com.intellij.util.containers.ConcurrentFactoryMap.<init>()

        Constructor gw.gosu.ij.codeInsight.GosuAnnotationUtil$3.<init>(GosuPsiModifierListOwner) contains an *invokespecial* instruction referencing a private constructor com.intellij.util.containers.ConcurrentFactoryMap.<init>() inaccessible to a class gw.gosu.ij.codeInsight.GosuAnnotationUtil$3. This can lead to **IllegalAccessError** exception at runtime.

        Constructor gw.gosu.ij.codeInsight.GosuAnnotationUtil$1.<init>(GosuPsiModifierListOwner) contains an *invokespecial* instruction referencing a private constructor com.intellij.util.containers.ConcurrentFactoryMap.<init>() inaccessible to a class gw.gosu.ij.codeInsight.GosuAnnotationUtil$1. This can lead to **IllegalAccessError** exception at runtime.

        Constructor gw.gosu.ij.codeInsight.GosuAnnotationUtil$2.<init>(GosuPsiModifierListOwner) contains an *invokespecial* instruction referencing a private constructor com.intellij.util.containers.ConcurrentFactoryMap.<init>() inaccessible to a class gw.gosu.ij.codeInsight.GosuAnnotationUtil$2. This can lead to **IllegalAccessError** exception at runtime.

    #Illegal invocation of package-private constructor com.intellij.util.containers.ConcurrentRefHashMap.<init>(int initialCapacity)

        Method gw.gosu.ij.codeInsight.daemon.impl.quickfix.CreateConstructorParameterFromFieldFix.getFieldsToFix() : Collection contains an *invokespecial* instruction referencing com.intellij.util.containers.ConcurrentWeakHashMap.<init>(int) which is resolved to a package-private constructor com.intellij.util.containers.ConcurrentRefHashMap.<init>(int) inaccessible to a class gw.gosu.ij.codeInsight.daemon.impl.quickfix.CreateConstructorParameterFromFieldFix. This can lead to **IllegalAccessError** exception at runtime.

        Method gw.gosu.ij.codeInsight.daemon.impl.quickfix.VariableAccessFromInnerClassFix.getVariablesToFix() : Collection contains an *invokespecial* instruction referencing com.intellij.util.containers.ConcurrentWeakHashMap.<init>(int) which is resolved to a package-private constructor com.intellij.util.containers.ConcurrentRefHashMap.<init>(int) inaccessible to a class gw.gosu.ij.codeInsight.daemon.impl.quickfix.VariableAccessFromInnerClassFix. This can lead to **IllegalAccessError** exception at runtime.

    #Invocation of unresolved constructor com.intellij.util.containers.ConcurrentWeakHashMap.<init>()

        Constructor gw.gosu.ij.psi.controlFlow.GosuControlFlowFactory.<init>(com.intellij.psi.impl.PsiManagerEx psiManager) contains an *invokespecial* instruction referencing an unresolved constructor com.intellij.util.containers.ConcurrentWeakHashMap.<init>(). This can lead to **NoSuchMethodError** exception at runtime.

        Method gw.gosu.ij.psi.infos.GosuMethodCandidateInfo.inferTypeArguments(gw.gosu.ij.psi.impl.source.resolve.GosuParameterTypeInferencePolicy project, gw.gosu.ij.psi.GosuPsiExpression[] gosuPsiFacade, boolean containingClass) : gw.gosu.ij.psi.GosuPsiSubstitutor contains an *invokespecial* instruction referencing an unresolved constructor com.intellij.util.containers.ConcurrentWeakHashMap.<init>(). This can lead to **NoSuchMethodError** exception at runtime.

    #Access to unresolved field com.intellij.codeInsight.daemon.impl.HighlightInfoType.ANNOTATION_ATTRIBUTE_NAME : HighlightInfoType

        Method gw.gosu.ij.codeInsight.daemon.impl.analysis.GosuHighlightVisitorImpl.visitNameValuePair(gw.gosu.ij.psi.GosuPsiNameValuePair this) : void contains a *getstatic* instruction referencing an unresolved field com.intellij.codeInsight.daemon.impl.HighlightInfoType.ANNOTATION_ATTRIBUTE_NAME : com.intellij.codeInsight.daemon.impl.HighlightInfoType. This can lead to **NoSuchFieldError** exception at runtime.

    #Invocation of unresolved method com.intellij.codeInspection.magicConstant.MagicCompletionContributor.getAllowedValues(PsiElement) : MagicConstantInspection.AllowedValues

        Method gw.gosu.ij.psi.filters.getters.GosuMembersGetter.addMembers(boolean searchInheritors, com.intellij.util.Consumer results) : void contains an *invokestatic* instruction referencing an unresolved method com.intellij.codeInspection.magicConstant.MagicCompletionContributor.getAllowedValues(com.intellij.psi.PsiElement) : com.intellij.codeInspection.magicConstant.MagicConstantInspection.AllowedValues. This can lead to **NoSuchMethodError** exception at runtime.

The method might have been declared in the super class: com.intellij.codeInsight.completion.CompletionContributor

    #Invocation of unresolved constructor com.intellij.util.containers.ConcurrentWeakHashMap.<init>(int)

        Method gw.gosu.ij.codeInsight.daemon.impl.quickfix.CreateConstructorParameterFromFieldFix.getFieldsToFix() : java.util.Collection contains an *invokespecial* instruction referencing an unresolved constructor com.intellij.util.containers.ConcurrentWeakHashMap.<init>(int). This can lead to **NoSuchMethodError** exception at runtime.

        Method gw.gosu.ij.codeInsight.daemon.impl.quickfix.VariableAccessFromInnerClassFix.getVariablesToFix() : java.util.Collection contains an *invokespecial* instruction referencing an unresolved constructor com.intellij.util.containers.ConcurrentWeakHashMap.<init>(int). This can lead to **NoSuchMethodError** exception at runtime.

    #Illegal invocation of package-private constructor com.intellij.util.containers.ConcurrentRefHashMap.<init>()

        Constructor gw.gosu.ij.psi.controlFlow.GosuControlFlowFactory.<init>(PsiManagerEx) contains an *invokespecial* instruction referencing com.intellij.util.containers.ConcurrentWeakHashMap.<init>() which is resolved to a package-private constructor com.intellij.util.containers.ConcurrentRefHashMap.<init>() inaccessible to a class gw.gosu.ij.psi.controlFlow.GosuControlFlowFactory. This can lead to **IllegalAccessError** exception at runtime.

        Method gw.gosu.ij.psi.infos.GosuMethodCandidateInfo.inferTypeArguments(GosuParameterTypeInferencePolicy, GosuPsiExpression[], boolean) : GosuPsiSubstitutor contains an *invokespecial* instruction referencing com.intellij.util.containers.ConcurrentWeakHashMap.<init>() which is resolved to a package-private constructor com.intellij.util.containers.ConcurrentRefHashMap.<init>() inaccessible to a class gw.gosu.ij.psi.infos.GosuMethodCandidateInfo. This can lead to **IllegalAccessError** exception at runtime.

    #Access to unresolved class com.intellij.psi.impl.PsiTreeChangePreprocessorBase

        Method gw.gosu.ij.psi.impl.GosuCodeBlockModificationListener.isOutOfCodeBlock(PsiFileSystemItem file) : boolean references an unresolved class com.intellij.psi.impl.PsiTreeChangePreprocessorBase. This can lead to **NoSuchClassError** exception at runtime.

        Constructor gw.gosu.ij.psi.impl.GosuCodeBlockModificationListener.<init>(PsiManager psiManager) references an unresolved class com.intellij.psi.impl.PsiTreeChangePreprocessorBase. This can lead to **NoSuchClassError** exception at runtime.

        Method gw.gosu.ij.psi.impl.GosuCodeBlockModificationListener.onTreeChanged(PsiTreeChangeEventImpl this) : void references an unresolved class com.intellij.psi.impl.PsiTreeChangePreprocessorBase. This can lead to **NoSuchClassError** exception at runtime.

        Class gw.gosu.ij.psi.impl.GosuCodeBlockModificationListener references an unresolved class com.intellij.psi.impl.PsiTreeChangePreprocessorBase. This can lead to **NoSuchClassError** exception at runtime.

    #Invocation of unresolved method com.intellij.psi.statistics.StatisticsInfo.getUseCount() : int

        Method gw.gosu.ij.psi.statistics.GosuStatisticsManager.getVariableNameUseCount(java.lang.String name, com.intellij.psi.codeStyle.VariableKind variableKind, java.lang.String propertyName, gw.gosu.ij.psi.GosuPsiType type) : int contains an *invokevirtual* instruction referencing an unresolved method com.intellij.psi.statistics.StatisticsInfo.getUseCount() : int. This can lead to **NoSuchMethodError** exception at runtime.

        Method gw.gosu.ij.codeInsight.daemon.impl.quickfix.GosuCreateFromUsageUtils.compareMembers(gw.gosu.ij.psi.GosuPsiMember m1, gw.gosu.ij.psi.GosuPsiMember m2, gw.gosu.ij.psi.GosuPsiExpression context) : int contains an *invokevirtual* instruction referencing an unresolved method com.intellij.psi.statistics.StatisticsInfo.getUseCount() : int. This can lead to **NoSuchMethodError** exception at runtime.

    #Access to unresolved field com.intellij.codeInsight.TailType.COMMA : TailType

        Method gw.gosu.ij.codeInsight.completion.GosuTypeArgumentCompletionProvider.getTail(boolean last) : com.intellij.codeInsight.TailType contains a *getstatic* instruction referencing an unresolved field com.intellij.codeInsight.TailType.COMMA : com.intellij.codeInsight.TailType. This can lead to **NoSuchFieldError** exception at runtime.

        Method gw.gosu.ij.codeInsight.lookup.GosuVariableLookupItem.handleInsert(com.intellij.codeInsight.completion.InsertionContext ref) : void contains a *getstatic* instruction referencing an unresolved field com.intellij.codeInsight.TailType.COMMA : com.intellij.codeInsight.TailType. This can lead to **NoSuchFieldError** exception at runtime.

        Method gw.gosu.ij.codeInsight.GosuExpectedTypesProvider.MyParentVisitor.getMethodArgumentTailType(gw.gosu.ij.psi.GosuPsiExpression call, int returnType, gw.gosu.ij.psi.GosuPsiMethod argument, gw.gosu.ij.psi.GosuPsiSubstitutor index, gw.gosu.ij.psi.GosuPsiParameter[] method) : com.intellij.codeInsight.TailType contains a *getstatic* instruction referencing an unresolved field com.intellij.codeInsight.TailType.COMMA : com.intellij.codeInsight.TailType. This can lead to **NoSuchFieldError** exception at runtime.

        Method gw.gosu.ij.codeInsight.completion.GosuDefaultInsertHandler.getTailType(char completionChar, com.intellij.codeInsight.lookup.LookupItem item) : com.intellij.codeInsight.TailType contains a *getstatic* instruction referencing an unresolved field com.intellij.codeInsight.TailType.COMMA : com.intellij.codeInsight.TailType. This can lead to **NoSuchFieldError** exception at runtime.

    #Invocation of unresolved constructor org.jetbrains.jps.incremental.storage.BuildDataManager.<init>(BuildDataPaths, BuildTargetsState, boolean)

        Method gw.gosu.ij.testframework.compiler.JpsBuildTestCase.createProjectDescriptor(org.jetbrains.jps.builders.logging.BuildLoggingManager index) : org.jetbrains.jps.cmdline.ProjectDescriptor contains an *invokespecial* instruction referencing an unresolved constructor org.jetbrains.jps.incremental.storage.BuildDataManager.<init>(org.jetbrains.jps.builders.storage.BuildDataPaths, org.jetbrains.jps.incremental.storage.BuildTargetsState, boolean). This can lead to **NoSuchMethodError** exception at runtime.

    #Invocation of unresolved constructor org.jetbrains.jps.cmdline.ProjectDescriptor.<init>(JpsModel, BuildFSState, ProjectTimestamps, BuildDataManager, BuildLoggingManager, ModuleExcludeIndex, BuildTargetsState, BuildTargetIndex, BuildRootIndex, IgnoredFileIndex)

        Method gw.gosu.ij.testframework.compiler.JpsBuildTestCase.createProjectDescriptor(org.jetbrains.jps.builders.logging.BuildLoggingManager index) : org.jetbrains.jps.cmdline.ProjectDescriptor contains an *invokespecial* instruction referencing an unresolved constructor org.jetbrains.jps.cmdline.ProjectDescriptor.<init>(org.jetbrains.jps.model.JpsModel, org.jetbrains.jps.incremental.fs.BuildFSState, org.jetbrains.jps.incremental.storage.ProjectTimestamps, org.jetbrains.jps.incremental.storage.BuildDataManager, org.jetbrains.jps.builders.logging.BuildLoggingManager, org.jetbrains.jps.indices.ModuleExcludeIndex, org.jetbrains.jps.incremental.storage.BuildTargetsState, org.jetbrains.jps.builders.BuildTargetIndex, org.jetbrains.jps.builders.BuildRootIndex, org.jetbrains.jps.indices.IgnoredFileIndex). This can lead to **NoSuchMethodError** exception at runtime.

    #Invocation of unresolved constructor org.jetbrains.jps.incremental.storage.ProjectTimestamps.<init>(File, BuildTargetsState)

        Method gw.gosu.ij.testframework.compiler.JpsBuildTestCase.createProjectDescriptor(org.jetbrains.jps.builders.logging.BuildLoggingManager index) : org.jetbrains.jps.cmdline.ProjectDescriptor contains an *invokespecial* instruction referencing an unresolved constructor org.jetbrains.jps.incremental.storage.ProjectTimestamps.<init>(java.io.File, org.jetbrains.jps.incremental.storage.BuildTargetsState). This can lead to **NoSuchMethodError** exception at runtime.

    #Invocation of unresolved method gw.gosu.ij.codeInsight.daemon.impl.GosuMarkerType.OverridingMethodsUpdater.getTheOnlyOneElement() : PsiElement

        Method gw.gosu.ij.codeInsight.daemon.impl.GosuMarkerType.OverridingMethodsUpdater.onFinished() : void contains an *invokevirtual* instruction referencing an unresolved method gw.gosu.ij.codeInsight.daemon.impl.GosuMarkerType.OverridingMethodsUpdater.getTheOnlyOneElement() : com.intellij.psi.PsiElement. This can lead to **NoSuchMethodError** exception at runtime.

The method might have been declared in the super classes or in the super interfaces:

  com.intellij.codeInsight.navigation.BackgroundUpdaterTask

  com.intellij.codeInsight.navigation.BackgroundUpdaterTaskBase

  com.intellij.codeInsight.navigation.ListBackgroundUpdaterTask

  com.intellij.openapi.progress.Task

  com.intellij.openapi.progress.Task.Backgroundable

  com.intellij.openapi.progress.PerformInBackgroundOption

  com.intellij.openapi.progress.Progressive

  com.intellij.openapi.progress.TaskInfo

    #Invocation of unresolved method com.intellij.psi.impl.search.PsiSearchHelperImpl.processTextOccurrences(PsiElement, String, GlobalSearchScope, Processor, UsageInfoFactory) : boolean

        Method gw.gosu.ij.find.findUsages.FindUsagesHelper.processUsagesInText(com.intellij.psi.PsiElement s, java.util.Collection element, com.intellij.psi.search.GlobalSearchScope stringToSearch, com.intellij.util.Processor searchScope) : boolean contains an *invokestatic* instruction referencing an unresolved method com.intellij.psi.impl.search.PsiSearchHelperImpl.processTextOccurrences(com.intellij.psi.PsiElement, java.lang.String, com.intellij.psi.search.GlobalSearchScope, com.intellij.util.Processor, com.intellij.usageView.UsageInfoFactory) : boolean. This can lead to **NoSuchMethodError** exception at runtime.

The method might have been declared in the super interface: com.intellij.psi.search.PsiSearchHelper

    #Illegal access to package-private class com.intellij.util.containers.WeakKeyWeakValueHashMap

        Package-private class com.intellij.util.containers.WeakKeyWeakValueHashMap is not available at gw.gosu.ij.codeInsight.GosuBaseExternalAnnotationsManager.<init>(PsiManager psiManager). This can lead to **IllegalAccessError** exception at runtime.

    #Access to unresolved class com.intellij.psi.SdkResolveScopeProvider

        Method gw.gosu.ij.psi.impl.source.GosuAndJavaSourceFilterScope.contains(VirtualFile provider) : boolean references an unresolved class com.intellij.psi.SdkResolveScopeProvider. This can lead to **NoSuchClassError** exception at runtime.

    #Illegal invocation of package-private constructor com.intellij.util.containers.WeakKeyWeakValueHashMap.<init>()

        Constructor gw.gosu.ij.codeInsight.GosuBaseExternalAnnotationsManager.<init>(PsiManager) contains an *invokespecial* instruction referencing a package-private constructor com.intellij.util.containers.WeakKeyWeakValueHashMap.<init>() inaccessible to a class gw.gosu.ij.codeInsight.GosuBaseExternalAnnotationsManager. This can lead to **IllegalAccessError** exception at runtime.

    #Package 'org.objectweb' is not found

        Package 'org.objectweb' is not found along with its 4 classes.

Probably the package 'org.objectweb' belongs to a library or dependency that is not resolved by the checker.

It is also possible, however, that this package was actually removed from a dependency causing the detected problems. Access to unresolved classes at runtime may lead to **NoSuchClassError**.

The following classes of 'org.objectweb' are not resolved:

  Class org.objectweb.asm.MethodVisitor is referenced in

    gw.gosu.ij.debug.ReloadClassesIndicatorCompiler.updateReloadClassesIndicator() : byte[]

    gw.gosu.ij.debug.ReloadClassesIndicatorCompiler.visitStringOrNull(MethodVisitor mv, String value) : void

  Class org.objectweb.asm.ClassWriter is referenced in

    gw.gosu.ij.debug.ReloadClassesIndicatorCompiler.updateReloadClassesIndicator() : byte[]

  Class org.objectweb.asm.Label is referenced in

    gw.gosu.ij.debug.ReloadClassesIndicatorCompiler.updateReloadClassesIndicator() : byte[]

  Class org.objectweb.asm.Opcodes is referenced in

    gw.gosu.ij.debug.ReloadClassesIndicatorCompiler

 

    #Invocation of unresolved method com.intellij.util.containers.ContainerUtilRt.newHashSet(int) : HashSet

        Constructor gw.gosu.ij.codeInspection.codeStyle.AnonymousCanBeBlockInspection.ForbiddenRefsChecker.<init>(gw.gosu.ij.psi.GosuPsiMethod method, gw.gosu.ij.psi.GosuPsiAnonymousClass aClass) contains an *invokestatic* instruction referencing an unresolved method com.intellij.util.containers.ContainerUtilRt.newHashSet(int) : java.util.HashSet. This can lead to **NoSuchMethodError** exception at runtime.

    #Invocation of unresolved constructor org.jetbrains.jps.builders.java.dependencyView.Mappings.<init>(File, boolean)

        Constructor org.jetbrains.jps.builders.java.dependencyView.GosuMappings.<init>(java.io.File rootDir, boolean transientDelta) contains an *invokespecial* instruction referencing an unresolved constructor org.jetbrains.jps.builders.java.dependencyView.Mappings.<init>(java.io.File, boolean). This can lead to **NoSuchMethodError** exception at runtime.

    #Access to unresolved field com.intellij.refactoring.JavaRefactoringSettings.MOVE_INNER_PREVIEW_USAGES : boolean

        Method gw.gosu.ij.refactoring.move.moveInner.GosuMoveInnerDialog.doAction() : void contains a *putfield* instruction referencing an unresolved field com.intellij.refactoring.JavaRefactoringSettings.MOVE_INNER_PREVIEW_USAGES : boolean. This can lead to **NoSuchFieldError** exception at runtime.

    #Access to unresolved field com.intellij.codeInsight.daemon.impl.HighlightInfoType.IMPLICIT_ANONYMOUS_CLASS_PARAMETER : HighlightInfoType

        Method gw.gosu.ij.codeInsight.daemon.impl.analysis.GosuHighlightVisitorImpl.doVisitReferenceElement(gw.gosu.ij.psi.PsiGosuCodeReferenceElement e) : gw.gosu.ij.psi.GosuResolveResult contains a *getstatic* instruction referencing an unresolved field com.intellij.codeInsight.daemon.impl.HighlightInfoType.IMPLICIT_ANONYMOUS_CLASS_PARAMETER : com.intellij.codeInsight.daemon.impl.HighlightInfoType. This can lead to **NoSuchFieldError** exception at runtime.

    #Invocation of unresolved method com.intellij.util.containers.ContainerUtilRt.newLinkedHashMap() : LinkedHashMap

        Method gw.gosu.ij.psi.codeStyle.GosuRearranger.<clinit>() : void contains an *invokestatic* instruction referencing an unresolved method com.intellij.util.containers.ContainerUtilRt.newLinkedHashMap() : java.util.LinkedHashMap. This can lead to **NoSuchMethodError** exception at runtime.

Against IC-193.4932.9 the plugin gw.gosu.ij:h-latest-user-rberlin-ISSTUDIO-527-SNAPSHOT has 0 warnings

2019-11-11T16:29:29 [main] INFO  verification - Total time spent downloading plugins and their dependencies: 0 ms

2019-11-11T16:29:29 [main] INFO  verification - Total amount of plugins and dependencies downloaded: 0 B

2019-11-11T16:29:29 [main] INFO  verification - Total amount of space used for plugins and dependencies: 0 B

 

0
Comment actions Permalink

Thanks for the detailed report and suggestions, we'll look into them.

 

BGoldberg: is this your plugin? https://plugins.jetbrains.com/plugin/7140-os-gosu All these errors are from upgrading 2019.2 vs 2019.3 only? Because the last release is marked as "2017.3.1 — 2017.3.7" only?! Are there sources available somewhere? Thanks. I"ll follow up on all the API breakages you listed.

0
Comment actions Permalink

Yes, that was apparently the last published version of our plugin in open source.  My company has continued developing the Gosu plugin for distribution to our own customers, and skipped 2018 and went from 2017.3.7 to 2019.x, but unfortunately the two people who know how to create the open source distribution at Guidewire left the company a few years ago, which is apparently why there are no further published versions, even though we have been actively developing this plugin for our customers.  

Guidewire has no objection to continuing publication of the plugin.  I will try to investigate how to publish later versions of that plugin.  If I am able to do so, or to provide you with sources of the 2019.1 plugin, it sounds like that will help JetBrains communicate with us what changes we need to make.  Is that the case?

Meanwhile, if you could follow up and provide us some guidance of how to deal with those breakages, while I try to figure out how to publish what we have for 2019.1,  that would help us greatly.

0
Comment actions Permalink

Actually, that's not our plugin, but rather Gosu (the language) itself.

0
Comment actions Permalink

Vladimir, regarding this:

> I would settle for having a @since java doc annotation for newly added or changed APIs with a minimum build number for its appearance

Actually this is already supported. We automatically generate '@ApiStatus.AvailableSince' annotations which describe build where API was introduced and publish them to IntelliJ Artifacts repository. If you use gradle-intellij-plugin to develop your plugin, these annotations will be automatically attached to the library when you import the project in IntelliJ IDEA, and there is an inspection which will show a warning if you for example access a method introduced in 192.xxx build while your plugin.xml has since-build=191.*.

0
Comment actions Permalink

BGoldberg, thanks for clarifying the publication status. Indeed, having a (recent) published version of your plugin on plugins.jetbrains.com is required for us to be aware of such problems. Publishing the sources is not necessary for the verification process, but may help in assisting on required changes.

I've updated the Breaking API Changes page http://www.jetbrains.org/intellij/sdk/docs/reference_guide/api_changes/api_changes_list_2019.html with some more items and hope to follow up with more in the next few days once I received necessary information.

0
Comment actions Permalink

Please follow this issue https://youtrack.jetbrains.com/issue/MP-2733 to track the ideas proposed above.

0

Please sign in to leave a comment.