2019.3 Beta Release RADICALLY Different from EAP versions

Answered

I just got a surprise with the Beta version of 2019.3.

I have been dutifully running tests on latest versions and all was going good. Until I got the Beta of the IDE.

First of all it comes with Kotlin 1.3.60 EAP, while EAP had 1.3.50. I have an old library written way back when Kotlin was still 1.0 and I was  experimenting with what I can do with Kotlin. The library is a dog and is on the chopping block but I was planning to do this after the cleanup I am doing.

This library fails completely with 1.3.60. There is no salvaging it. I tried. I know it is my problem, but going from EAP to Beta with major changes that break what worked in previous releases and all EAPs seems to defeat the point of working with EAP releases since they do not reflect what's coming.

There are also a lot more stringent checks on what can be done during component initialization and this is causing failures of my plugin. Again, I know it is my problem and I cleaned that up, but it would be really nice to get a heads up with the EAP releases instead of finding out about when Beta rolls out.

I love the IDE and can't live without it but maintaining plugins for it is a PITA. I tried everything, using latest EAP versions, using daily snapshot builds to get a heads up of what to expect in the new release. And I still feel like the rug is pulled from under my feet as the release approaches.

Meanwhile, users think that I coded the plugin four years ago and now I am sitting on my behind, doing nothing but collecting license fees. ZZ-TOP lyrics come to mind: "money for nothing and chicks for free"

8 comments
Comment actions Permalink

Hello Vladimir,

Thanks for your report. I'd like to request the following information to better understand:

Could you please explain what kind of incompatibilities you experienced going from Kotlin 1.3.50 to 1.3.60?

 

There are also a lot more stringent checks on what can be done during component initialization and this is causing failures of my plugin.

Could you give some concrete examples, please?

 

Thanks!

0
Comment actions Permalink

Hi Yann,

Kotlin 1.30.60 differences: open method invocation during construction behaves differently than 1.30.50 and all prior versions. Specifically, from observation of code execution, where previously there was partial initialization of the derived class, now the derived class is not initialized until the super class is fully constructed. Calls to subclassed methods from super class constructor, get values in subclassed fields which are now consistently null where in previous versions they contained initialized values from partially constructed sub-class.

It is not a Kotlin problem. I prefer strict enforcement and consistency of the current version. Unfortunately, when I wrote the library, Kotlin was in diapers and figuring out initialization order was a trial and error experience. I was planning to ditch the library as soon as possible and was in the process of preparing for the replacement. Not a walk in the park because I wound up using some of the library's functionality for ALL text gathering, transformation and formatting. Yup, all over the place with implementation dependency on quirky  behaviour of those classes, silently folded into the current code for added measure of fun.

This forced me to ditch it sooner than I was ready but necessity is the mother of invention.

More stringent checks: old code was causing the loading of the plugin's language SyntaxHighlighter in the plugin's initializeComponent() method. The latest version generates an exception complaining that the call should be made when state is initialized, instead the state is .... I already fixed the code so do not have the exact exception. The latter implementation was also in old Kotlin code that needed attention and it got that attention sooner than planned.

Kotlin 1.30.60 differences: There was an exception for access violations in my SyntaxHighlighterBase derived class, written in Kotlin. The exception complained that an attempt was made to access a protected method (of SyntaxHighlighterBase) from the companion object method (of the subclass extending the SyntaxHighlighterBase). I did not bother investigating what the issue was. I just implemented the simple method in my own class and went on to other issues.

My issue is not with making changes or improvements. I am all for it. My shock is that going through all EAP releases, Preview Releases and Release Candidates means nothing for compatibility with the next more stable release. I have seen breaking changes introduced between RCx releases. Which means that there is major s**t being changed in the implementation in late phases of the release cycle, Usually this would require bumping down the release candidate to at least Beta to allow time for downstream dependents (ie. plugin developers) to prepare for the incompatibility. Instead, the next RCx label gets slapped on the release and away it goes.

Effectively, I have no confidence of having a compatible plugin until the final release is made and I try it out.

 

0
Comment actions Permalink

Hi Vladimir,

I don't quite understand why differences between Kotlin versions caused problems for you. Note that there are 3 different versions of Kotlin which may affect plugin development:

1) version of kotlin-stdlib library bundled with IntelliJ platform. The current version is 1.3.31 and it wasn't changed since 2019.2. If you want to use a different (newer) version of kotlin-stdlib you can bundle it with your plugin and it'll be used instead the platform one.

2) version of Kotlin compiler which is used to compile the plugin's code. It is specified in plugin's build scripts and changes in IDE doesn't affect it. You can use any version of Kotlin compiler provided that it's compatible with version of kotlin-stdlib in your plugin.

3) version of Kotlin plugin bundled with IntelliJ IDEA. This version is different for different IDE builds (e.g. we're going to bundle 1.3.60 release of Kotlin with the final release of IntelliJ IDEA 2019.3 so it's natural that we started bundling EAPs of Kotlin plugin with pre-release builds of IntelliJ IDEA). Version of bundled Kotlin plugin may affect your plugin only if your plugin depends on Kotlin plugin and uses its API. Is it the case?

0
Comment actions Permalink

Nikolay, I have plugin failure caused by that infamous library written in Kotlin, only in 2019.3 Beta with Kotlin plugin 1.30.60.

No recompilation of the plugin. I tried the last released version of the plugin and it failed the same way as my dev environment. My plugin does not depend on the Kotlin plugin, only on the bundled Kotlin run-time since I stopped bundling Kotlin run time with the plugin when all IDEs started bundling it because my plugin does not rely on the latest Kotlin.

It sounds like I should put the Kotlin run-time back into the plugin distribution to stay safe. I will try that to see if it solves the problem for that version.

However, there is a difference in the compiler and run-time in 1.30.60 that breaks backward compatibility because when I patched the 2019.3 Beta with Kotlin plugin version 1.30.50 everything worked like before. No run-time failures. With 1.30.60 the library fails at run-time and will not compile. The latter is not a problem as far as I am concerned. Crap code should not compile.

The run-time however should not fail if it worked with previous versions, without major version changes to signal backward compatibility breaks.

Am I missing something on the backward compatibility part or does this library do something so alien that it breaks backward compatibility no one knew about?

0
Comment actions Permalink

Yann, here is the initialization exception. This time it is not in my plugin but in Database Tools plugin:

Should be called at least in the state COMPONENTS_LOADED, the current state is: CONFIGURATION_STORE_INITIALIZED
Current violators count: 1
 
 
 
java.lang.Throwable
at com.intellij.diagnostic.LoadingState.logStateError(LoadingState.java:55)
at com.intellij.diagnostic.LoadingState.checkOccurred(LoadingState.java:51)
at com.intellij.psi.tree.IElementType.<init>(IElementType.java:91)
at com.intellij.sql.psi.SqlElementType.<init>(SqlElementType.java:16)
at com.intellij.sql.psi.SqlCompositeElementType.<init>(SqlCompositeElementType.java:13)
at com.intellij.sql.psi.SqlReferenceElementType.<init>(SqlReferenceElementType.java:20)
at com.intellij.sql.psi.SqlReferenceElementType.lambda$factory$0(SqlReferenceElementType.java:16)
at com.intellij.sql.util.SqlTokenRegistry.getImpl(SqlTokenRegistry.java:85)
at com.intellij.sql.util.SqlTokenRegistry.getCompositeType(SqlTokenRegistry.java:67)
at com.intellij.sql.psi.SqlCompositeElementTypes.getCompositeRefType(SqlCompositeElementTypes.java:379)
at com.intellij.sql.psi.SqlCompositeElementTypes.<clinit>(SqlCompositeElementTypes.java:23)
at com.intellij.database.dialects.oracle.debugger.OraDebuggerFacade.<clinit>(OraDebuggerFacade.kt:20)
at com.intellij.database.dialects.oracle.debugger.OraDebuggerSettingsExtension.getState(OraDebuggerSettingsExtension.kt:27)
at com.intellij.database.dialects.oracle.debugger.OraDebuggerSettingsExtension.getState(OraDebuggerSettingsExtension.kt:10)
at com.intellij.xdebugger.impl.settings.XDebuggerSettingManagerImpl.getState(XDebuggerSettingManagerImpl.java:45)
at com.intellij.xdebugger.impl.settings.XDebuggerSettingManagerImpl.getState(XDebuggerSettingManagerImpl.java:25)
at com.intellij.configurationStore.StateGetterImpl.archiveState(StorageBaseEx.kt:66)
at com.intellij.configurationStore.ComponentStoreImpl.doInitComponent(ComponentStoreImpl.kt:413)
at com.intellij.configurationStore.ComponentStoreImpl.initComponent(ComponentStoreImpl.kt:363)
at com.intellij.configurationStore.ComponentStoreImpl.initPersistenceStateComponent(ComponentStoreImpl.kt:130)
at com.intellij.configurationStore.ComponentStoreImpl.initComponent(ComponentStoreImpl.kt:96)
at com.intellij.configurationStore.ComponentStoreWithExtraComponents.initComponent(ComponentStoreWithExtraComponents.kt:49)
at com.intellij.serviceContainer.PlatformComponentManagerImpl.initializeComponent(PlatformComponentManagerImpl.kt:259)
at com.intellij.serviceContainer.ServiceComponentAdapter.createAndInitialize(ServiceComponentAdapter.kt:56)
at com.intellij.serviceContainer.ServiceComponentAdapter.access$createAndInitialize(ServiceComponentAdapter.kt:15)
at com.intellij.serviceContainer.ServiceComponentAdapter$doCreateInstance$$inlined$use$lambda$1.run(ServiceComponentAdapter.kt:44)
at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:585)
at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:531)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:59)
at com.intellij.openapi.progress.impl.CoreProgressManager.executeNonCancelableSection(CoreProgressManager.java:191)
at com.intellij.serviceContainer.ServiceComponentAdapter.doCreateInstance(ServiceComponentAdapter.kt:43)
at com.intellij.serviceContainer.BaseComponentAdapter.getInstanceUncached(BaseComponentAdapter.kt:110)
at com.intellij.serviceContainer.BaseComponentAdapter.getInstance(BaseComponentAdapter.kt:72)
at com.intellij.serviceContainer.BaseComponentAdapter.getInstance$default(BaseComponentAdapter.kt:65)
at com.intellij.serviceContainer.PlatformComponentManagerImpl.getService(PlatformComponentManagerImpl.kt:289)
at com.intellij.openapi.components.ServiceManager.getService(ServiceManager.java:18)
at com.intellij.xdebugger.settings.XDebuggerSettingsManager.getInstance(XDebuggerSettingsManager.java:23)
at com.intellij.xdebugger.impl.settings.XDebuggerSettingManagerImpl.getInstanceImpl(XDebuggerSettingManagerImpl.java:33)
at com.intellij.xdebugger.impl.XDebuggerUtilImpl.getDebuggerSettings(XDebuggerUtilImpl.java:395)
at org.jetbrains.kotlin.idea.debugger.KotlinDebuggerSettings$Companion.getInstance(KotlinDebuggerSettings.kt:28)
at org.jetbrains.kotlin.idea.debugger.filter.DebuggerFiltersUtilKt.addKotlinStdlibDebugFilterIfNeeded(DebuggerFiltersUtil.kt:26)
at org.jetbrains.kotlin.idea.JvmPluginStartupComponent.initComponent(JvmPluginStartupComponent.java:41)
at com.intellij.serviceContainer.MyComponentAdapter.doCreateInstance(MyComponentAdapter.kt:42)
at com.intellij.serviceContainer.BaseComponentAdapter.getInstanceUncached(BaseComponentAdapter.kt:110)
at com.intellij.serviceContainer.BaseComponentAdapter.getInstance(BaseComponentAdapter.kt:72)
at com.intellij.serviceContainer.BaseComponentAdapter.getInstance$default(BaseComponentAdapter.kt:65)
at com.intellij.serviceContainer.PlatformComponentManagerImpl.createComponents(PlatformComponentManagerImpl.kt:178)
at com.intellij.openapi.application.impl.ApplicationImpl.lambda$loadComponents$3(ApplicationImpl.java:346)
at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$2(CoreProgressManager.java:163)
at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:585)
at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:531)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:59)
at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:150)
at com.intellij.openapi.application.impl.ApplicationImpl.loadComponents(ApplicationImpl.java:346)
at com.intellij.idea.ApplicationLoader$startApp$6$loadComponentInEdtFuture$1.run(ApplicationLoader.kt:206)
at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:776)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:727)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:746)
at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:396)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

 

0
Comment actions Permalink

https://youtrack.jetbrains.com/issue/DBE-9449 Please report such errors in YouTrack, it will be easier to assign/monitor them, thanks.

0
Comment actions Permalink

Yann, I was not reporting an error. I was giving a concrete example of breaking changes from EAP to BEATA that even JetBrains produced plugins trip over.

0
Comment actions Permalink

Ok sorry, I misunderstood your intent then.

0

Please sign in to leave a comment.