Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(editors/intellij): IntelliJ Platform LSP #185

Merged
merged 19 commits into from
Sep 20, 2023

Conversation

victor-teles
Copy link
Contributor

@victor-teles victor-teles commented Sep 7, 2023

Summary

Closes #93

Tasks

  • Automatic find biome binary from node_modules
  • Provide code formatting (using cli)
  • Linting
  • Statusbar widget same as VSCode "Biome ${version}"
  • Setting to change the path of the binary
  • QuickFix
  • Toolbar action for restart server
  • Automatic restart LSP when biome.json change and settings changes
  • Instructions for local development
  • Add Github workflows

@victor-teles victor-teles changed the title feat(editors/intellij): :wip: initial implementation feat(editors/intellij): IntelliJ Platform LSP Sep 7, 2023
@victor-teles
Copy link
Contributor Author

@Conaclos @ematipico

Secrets

I am working on the Github workflows right now and to get this done, i need some Github secrets to release the plugin on Jetbrains Marketplace:

Suggested secret name Description
JETBRAINS_PUBLISH_TOKEN Token to authenticate on jetbrains API (get here : https://plugins.jetbrains.com/author/me/tokens)
JETBRAINS_CERTIFICATE_CHAIN Certificate chain to sign the plugin (how to get: https://plugins.jetbrains.com/docs/intellij/plugin-signing.html#signing-methods)
JETBRAINS_PRIVATE_KEY Certificate private key
JETBRAINS_PRIVATE_KEY_PASSWORD Private key password

For more details about publishing a plugin: https://plugins.jetbrains.com/docs/intellij/publishing-plugin.html#uploading-a-plugin-to-jetbrains-marketplace

Workflow dispatch

I also need to understand which workflow_dispatch's strategy is better for this workflow

Can you explain how current release process works for vscode (how its triggered, version bump...)?

@ematipico
Copy link
Member

@Conaclos @ematipico

Secrets

I am working on the Github workflows right now and to get this done, i need some Github secrets to release the plugin on Jetbrains Marketplace:
Suggested secret name Description
JETBRAINS_PUBLISH_TOKEN Token to authenticate on jetbrains API (get here : plugins.jetbrains.com/author/me/tokens)
JETBRAINS_CERTIFICATE_CHAIN Certificate chain to sign the plugin (how to get: plugins.jetbrains.com/docs/intellij/plugin-signing.html#signing-methods)
JETBRAINS_PRIVATE_KEY Certificate private key
JETBRAINS_PRIVATE_KEY_PASSWORD Private key password

For more details about publishing a plugin: plugins.jetbrains.com/docs/intellij/publishing-plugin.html#uploading-a-plugin-to-jetbrains-marketplace

Done. This info is stored in the environment intellij-plugin.

Workflow dispatch

I also need to understand which workflow_dispatch's strategy is better for this workflow

Can you explain how current release process works for vscode (how its triggered, version bump...)?

You might want to update this workflow: https://github.com/biomejs/biome/blob/main/.github/workflows/release_lsp.yml

We have two kinds of releases: nightly (pre-release) and official releases:

  • nightly: it's triggered every night, or it's manually triggered. We update the version using a script and then --pre-release CLI flag.
  • Stable: It's triggered when the version of the package.json of the extension changes.

We bump the version manually. We use even numbers for releases, and odd numbers for pre-releases (more here).

Anything else you need to know?

@victor-teles
Copy link
Contributor Author

@ematipico
Thank you for clarifying.

Do you mind if for now i create a separated workflow file from release_lsp.yml?

The release_lsp today also build and pack the biome binary into the vsix and for intellij its not necessary because the plugin resolve de binary from node_modules

@ematipico
Copy link
Member

@ematipico
Thank you for clarifying.

Do you mind if for now i create a separated workflow file from release_lsp.yml?

The release_lsp today also build and pack the biome binary into the vsix and for intellij its not necessary because the plugin resolve de binary from node_modules

Ideally we would want to build also the binary, but I think we can skip for now, and focus on publishing the plugin via workflow.

You might want to create the workflow in a different PR, so we can merge it, and we can use this PR to test the workflow by using the workflow dispatch.

@denbezrukov
Copy link
Contributor

denbezrukov commented Sep 13, 2023

Huge thanks for the review @alexander-doroshko:

LSP-related classes LGTM.
A few comments:

  1. I don’t see any need in empty classes BiomeLspCodeActionsSupport and BiomeLspDiagnosticsSupport. Unless any additions in these classes planned, I’d suggest to remove them and not to override lspDiagnosticsSupport and lspCodeActionsSupport at all.
  2. I’m curious what is the purpose of overriding clientCapabilities. Basically, what the plugin currently says, is that it is not able to do anything, even code highlighting. What LSP features are used? Only diagnostics? Does the server ignore client capabilities and send diagnostics anyway? Do you want to disable quick fixes and code completion? I don’t think you need to override clientCapabilities for that
  3. BiomeUtils.isSupportedFileType looks suspicious. Why checking FileType.defultExtensions? Maybe simply check file extension? Or file type instance?

@victor-teles
Copy link
Contributor Author

victor-teles commented Sep 13, 2023

@ematipico

You might want to create the workflow in a different PR, so we can merge it, and we can use this PR to test the workflow by using the workflow dispatch.

Ok, gonna do that

@denbezrukov

About 1 and 2

I just created that files and override clientCapabilities for testing purpose, because i was investigating a bug with quickfixes (resolved by #248)
I gonna remove all files and the override as suggested

3 - Don't know exactly why this method is checking FileType.defultExtensions 💯
(Get that code from rome/tools#4658)
I will update as suggested

@victor-teles victor-teles marked this pull request as ready for review September 13, 2023 21:16
@victor-teles
Copy link
Contributor Author

@ematipico I've just added the workflows
Could you help me with the tests and code review?

Copy link
Member

@ematipico ematipico left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left some feedback.

Could you update CONTRIBUTING.md with some instructions on how to run the plugin locally? So we can help testing it

Comment on lines +66 to +69
return GeneralCommandLine()
.withWorkDirectory(project.basePath)
.withExePath(binaryPath)
.withParameters("--version")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the expected output of this function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createVersionCommandLine only creates the instance of GeneralCommandLine class (Used to run the biome --version command)

I use it to extract the biome's version and use on the toolbar
But now i think the regex is not 100% right for semver

@ematipico
Copy link
Member

BTW, thank you for this amazing contribution!

Copy link
Contributor

@nissy-dev nissy-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your work is really appreciated for supporting intellij plugin! This is many users wanted.

I reviewed and tested this plugin. I couldn't check the plugin work well by running./gradlew runIde and setting biome bin path on my end. Do I need to do any additional steps?

And then, when checking the plugin, I got the following errors. These errors might be related?

java.lang.Throwable: Write-unsafe context! Model changes are allowed from write-safe contexts only. Please ensure you're using invokeLater/invokeAndWait with a correct modality state (not "any"). See TransactionGuard documentation for details.
java.lang.Throwable: Write-unsafe context! Model changes are allowed from write-safe contexts only. Please ensure you're using invokeLater/invokeAndWait with a correct modality state (not "any"). See TransactionGuard documentation for details.
  current modality=ModalityState:{[Biome is loading... 1406936926: running=false; canceled=false]}
	at com.intellij.openapi.diagnostic.Logger.error(Logger.java:370)
	at com.intellij.openapi.application.TransactionGuardImpl.assertWriteSafeContext(TransactionGuardImpl.java:151)
	at com.intellij.openapi.vfs.newvfs.RefreshSessionImpl.(RefreshSessionImpl.java:62)
	at com.intellij.openapi.vfs.newvfs.RefreshQueueImpl.createSession(RefreshQueueImpl.java:184)
	at com.intellij.openapi.vfs.newvfs.RefreshQueue.refresh(RefreshQueue.java:39)
	at com.intellij.openapi.vfs.newvfs.RefreshQueue.refresh(RefreshQueue.java:27)
	at com.intellij.openapi.vfs.newvfs.NewVirtualFile.refresh(NewVirtualFile.java:56)
	at com.intellij.openapi.vfs.VirtualFile.refresh(VirtualFile.java:675)
	at com.intellij.ide.plugins.DynamicPluginsFrameStateListener.applicationActivated(DynamicPluginVfsListener.kt:137)
	at com.intellij.util.messages.impl.MessageBusImplKt.invokeMethod(MessageBusImpl.kt:699)
	at com.intellij.util.messages.impl.MessageBusImplKt.invokeListener(MessageBusImpl.kt:663)
	at com.intellij.util.messages.impl.MessageBusImplKt.deliverMessage(MessageBusImpl.kt:422)
	at com.intellij.util.messages.impl.MessageBusImplKt.pumpWaiting(MessageBusImpl.kt:401)
	at com.intellij.util.messages.impl.MessageBusImplKt.access$pumpWaiting(MessageBusImpl.kt:1)
	at com.intellij.util.messages.impl.MessagePublisher.invoke(MessageBusImpl.kt:460)
	at jdk.proxy2/jdk.proxy2.$Proxy161.applicationActivated(Unknown Source)
	at com.intellij.ide.ApplicationActivationStateManager.setActive(ApplicationActivationStateManager.java:105)
	at com.intellij.ide.ApplicationActivationStateManager.updateState(ApplicationActivationStateManager.java:48)
	at com.intellij.ide.IdeEventQueueKt.processAppActivationEvent(IdeEventQueue.kt:1031)
	at com.intellij.ide.IdeEventQueueKt.access$processAppActivationEvent(IdeEventQueue.kt:1)
	at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.kt:573)
	at com.intellij.ide.IdeEventQueue.access$_dispatchEvent(IdeEventQueue.kt:67)
	at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:369)
	at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:368)
	at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:787)
	at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:368)
	at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:363)
	at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$1(IdeEventQueue.kt:992)
	at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:105)
	at com.intellij.ide.IdeEventQueueKt.performActivity(IdeEventQueue.kt:992)
	at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$7(IdeEventQueue.kt:363)
	at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:861)
	at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.kt:405)
	at java.desktop/java.awt.SentEvent.dispatch(SentEvent.java:75)
	at java.desktop/java.awt.DefaultKeyboardFocusManager$DefaultKeyboardFocusManagerSentEvent.dispatch(DefaultKeyboardFocusManager.java:262)
	at java.desktop/java.awt.DefaultKeyboardFocusManager.sendMessage(DefaultKeyboardFocusManager.java:289)
	at java.desktop/java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:439)
	at com.intellij.ide.IdeKeyboardFocusManager.access$dispatchEvent$s1569605750(IdeKeyboardFocusManager.kt:18)
	at com.intellij.ide.IdeKeyboardFocusManager$dispatchEvent$1.invoke(IdeKeyboardFocusManager.kt:25)
	at com.intellij.ide.IdeKeyboardFocusManager$dispatchEvent$1.invoke(IdeKeyboardFocusManager.kt:25)
	at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$1(IdeEventQueue.kt:992)
	at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:105)
	at com.intellij.ide.IdeEventQueueKt.performActivity(IdeEventQueue.kt:992)
	at com.intellij.ide.IdeKeyboardFocusManager.dispatchEvent(IdeKeyboardFocusManager.kt:25)
	at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4904)
	at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
	at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2808)
	at java.desktop/java.awt.Component.dispatchEvent(Component.java:4855)
	at java.desktop/sun.awt.SunToolkit$1.run(SunToolkit.java:524)
	at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:792)
	at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:739)
	at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:733)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:761)
	at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.kt:685)
	at com.intellij.ide.IdeEventQueue._dispatchEvent$lambda$10(IdeEventQueue.kt:589)
	at com.intellij.openapi.application.impl.ApplicationImpl.runWithoutImplicitRead(ApplicationImpl.java:1485)
	at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.kt:589)
	at com.intellij.ide.IdeEventQueue.access$_dispatchEvent(IdeEventQueue.kt:67)
	at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:369)
	at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:368)
	at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:787)
	at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:368)
	at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:363)
	at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$1(IdeEventQueue.kt:992)
	at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:105)
	at com.intellij.ide.IdeEventQueueKt.performActivity(IdeEventQueue.kt:992)
	at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$7(IdeEventQueue.kt:363)
	at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:861)
	at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.kt:405)
	at com.intellij.ide.IdeEventQueue.pumpEventsForHierarchy(IdeEventQueue.kt:721)
	at com.intellij.openapi.progress.util.ProgressWindow.lambda$startBlocking$4(ProgressWindow.java:217)
	at com.intellij.openapi.application.impl.ApplicationImpl.runUnlockingIntendedWrite(ApplicationImpl.java:887)
	at com.intellij.openapi.progress.util.ProgressWindow.lambda$startBlocking$5(ProgressWindow.java:212)
	at com.intellij.openapi.progress.util.ProgressWindow.executeInModalContext(ProgressWindow.java:193)
	at com.intellij.openapi.progress.util.ProgressWindow.startBlocking(ProgressWindow.java:210)
	at com.intellij.openapi.progress.impl.ProgressRunner.lambda$execFromEDT$7(ProgressRunner.java:317)
	at java.base/java.util.concurrent.CompletableFuture.uniAcceptNow(CompletableFuture.java:757)
	at java.base/java.util.concurrent.CompletableFuture.uniAcceptStage(CompletableFuture.java:735)
	at java.base/java.util.concurrent.CompletableFuture.thenAccept(CompletableFuture.java:2182)
	at com.intellij.openapi.progress.impl.ProgressRunner.execFromEDT(ProgressRunner.java:314)
	at com.intellij.openapi.progress.impl.ProgressRunner.submit(ProgressRunner.java:254)
	at com.intellij.openapi.progress.impl.ProgressRunner.submitAndGet(ProgressRunner.java:195)
	at com.intellij.openapi.application.impl.ApplicationImpl.runProcessWithProgressSynchronously(ApplicationImpl.java:445)
	at com.intellij.openapi.progress.impl.CoreProgressManager.runProcessWithProgressSynchronously(CoreProgressManager.java:523)
	at com.intellij.openapi.progress.impl.ProgressManagerImpl.runProcessWithProgressSynchronously(ProgressManagerImpl.java:86)
	at com.intellij.openapi.progress.impl.CoreProgressManager.runProcessWithProgressSynchronously(CoreProgressManager.java:248)
	at com.github.biomejs.intellijbiome.widgets.BiomeWidgetPresentation.getSelectedValue(BiomeWidgetPresentation.kt:22)
	at com.intellij.openapi.wm.impl.status.MultipleTextValues.(IdeStatusBarImpl.kt:911)
	at com.intellij.openapi.wm.impl.status.IdeStatusBarImplKt.createComponentByWidgetPresentation(IdeStatusBarImpl.kt:816)
	at com.intellij.openapi.wm.impl.status.IdeStatusBarImplKt.wrap(IdeStatusBarImpl.kt:834)
	at com.intellij.openapi.wm.impl.status.IdeStatusBarImplKt.access$wrap(IdeStatusBarImpl.kt:1)
	at com.intellij.openapi.wm.impl.status.IdeStatusBarImpl$doInit$items$1$1$component$1$1.invoke(IdeStatusBarImpl.kt:298)
	at com.intellij.openapi.wm.impl.status.IdeStatusBarImpl$doInit$items$1$1$component$1$1.invoke(IdeStatusBarImpl.kt:297)
	at com.intellij.openapi.progress.CoroutinesKt.blockingContext(coroutines.kt:248)
	at com.intellij.openapi.progress.CoroutinesKt.blockingContext(coroutines.kt:199)
	at com.intellij.openapi.wm.impl.status.IdeStatusBarImpl$doInit$items$1$1$component$1.invokeSuspend(IdeStatusBarImpl.kt:297)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at com.intellij.openapi.application.TransactionGuardImpl$1.run(TransactionGuardImpl.java:193)
	at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:861)
	at com.intellij.openapi.application.impl.ApplicationImpl$4.run(ApplicationImpl.java:478)
	at com.intellij.openapi.application.impl.FlushQueue.doRun(FlushQueue.java:79)
	at com.intellij.openapi.application.impl.FlushQueue.runNextEvent(FlushQueue.java:121)
	at com.intellij.openapi.application.impl.FlushQueue.flushNow(FlushQueue.java:41)
	at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:792)
	at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:739)
	at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:733)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:761)
	at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.kt:685)
	at com.intellij.ide.IdeEventQueue._dispatchEvent$lambda$10(IdeEventQueue.kt:589)
	at com.intellij.openapi.application.impl.ApplicationImpl.runWithoutImplicitRead(ApplicationImpl.java:1485)
	at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.kt:589)
	at com.intellij.ide.IdeEventQueue.access$_dispatchEvent(IdeEventQueue.kt:67)
	at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:369)
	at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:368)
	at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:787)
	at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:368)
	at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:363)
	at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$1(IdeEventQueue.kt:992)
	at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:105)
	at com.intellij.ide.IdeEventQueueKt.performActivity(IdeEventQueue.kt:992)
	at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$7(IdeEventQueue.kt:363)
	at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:861)
	at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.kt:405)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92)
  
Java.util.NoSuchElementException: List is empty.
java.util.NoSuchElementException: List is empty.
	at kotlin.collections.CollectionsKt___CollectionsKt.first(_Collections.kt:214)
	at kotlin.collections.CollectionsKt___CollectionsKt.first(_Collections.kt:197)
	at com.github.biomejs.intellijbiome.widgets.BiomeWidgetPresentation.getTooltipText(BiomeWidgetPresentation.kt:32)
	at com.intellij.openapi.wm.impl.status.MultipleTextValues$1.invoke(IdeStatusBarImpl.kt:908)
	at com.intellij.openapi.wm.impl.status.MultipleTextValues$1.invoke(IdeStatusBarImpl.kt:908)
	at com.intellij.openapi.wm.impl.status.TextPanel.getToolTipText(TextPanel.kt:53)
	at java.desktop/javax.swing.JComponent.getToolTipText(JComponent.java:3100)
	at com.intellij.ide.IdeTooltipManager.isTooltipDefined(IdeTooltipManager.java:261)
	at com.intellij.ide.IdeTooltipManager.showForComponent(IdeTooltipManager.java:230)
	at com.intellij.ide.IdeTooltipManager.maybeShowFor(IdeTooltipManager.java:217)
	at com.intellij.ide.IdeTooltipManager.eventDispatched(IdeTooltipManager.java:140)
	at java.desktop/java.awt.Toolkit$SelectiveAWTEventListener.eventDispatched(Toolkit.java:2202)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2094)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2093)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2093)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2093)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2093)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2093)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2093)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2093)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2093)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2093)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2093)
	at java.desktop/java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Toolkit.java:2093)
	at java.desktop/java.awt.Toolkit.notifyAWTEventListeners(Toolkit.java:2050)
	at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4933)
	at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
	at java.desktop/java.awt.Component.dispatchEvent(Component.java:4855)
	at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4954)
	at java.desktop/java.awt.LightweightDispatcher.retargetMouseEnterExit(Container.java:4732)
	at java.desktop/java.awt.LightweightDispatcher.trackMouseEnterExit(Container.java:4710)
	at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4561)
	at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4522)
	at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
	at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2808)
	at java.desktop/java.awt.Component.dispatchEvent(Component.java:4855)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:794)
	at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:739)
	at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:733)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:766)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:764)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:763)
	at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.kt:685)
	at com.intellij.ide.IdeEventQueue.dispatchMouseEvent(IdeEventQueue.kt:633)
	at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.kt:588)
	at com.intellij.ide.IdeEventQueue.access$_dispatchEvent(IdeEventQueue.kt:67)
	at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:369)
	at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:368)
	at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:787)
	at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:368)
	at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:363)
	at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$1(IdeEventQueue.kt:992)
	at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:113)
	at com.intellij.ide.IdeEventQueueKt.performActivity(IdeEventQueue.kt:992)
	at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$7(IdeEventQueue.kt:363)
	at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:861)
	at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.kt:405)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92)
  

editors/intellij/CHANGELOG.md Outdated Show resolved Hide resolved
editors/intellij/build.gradle.kts Outdated Show resolved Hide resolved
editors/intellij/gradle.properties Outdated Show resolved Hide resolved
editors/intellij/gradle.properties Outdated Show resolved Hide resolved
editors/intellij/src/main/resources/META-INF/plugin.xml Outdated Show resolved Hide resolved
@victor-teles
Copy link
Contributor Author

victor-teles commented Sep 18, 2023

BTW, thank you for this amazing contribution!

Would like to extend thanks to @magnetardev for his preliminary work.

@nissy-dev Hey, thank you for the review, really appreciate that!

I reviewed and tested this plugin. I couldn't check the plugin work well by running./gradlew runIde and setting biome bin path on my end. Do I need to do any additional steps?
And then, when checking the plugin, I got the following errors. These errors might be related?

Your CLI path point to a valid CLI? (if not, maybe we need some extra validations for invalid paths)

Copy link
Contributor

@nissy-dev nissy-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your CLI path point to a valid CLI? (if not, maybe we need some extra validations for invalid paths)

I could confirm that the latest state of this branch is working fine!

What is the status of the format, the code about the format exists, but does it still need to be modified? Also, it would be helpful if you could format all code before committing it.

@victor-teles
Copy link
Contributor Author

@nissy-dev

What is the status of the format, the code about the format exists, but does it still need to be modified?

Are you talking about BiomeFormatterProvider? if yes, i think it is working
You can use Format code with ⌥⇧ ⌘ L or Ctrl+Alt+L
Let me know if it is not working for you

Also, it would be helpful if you could format all code before committing it.

Do you mean format the kotlin code, right?
I think we could configure ktLint & ktLintIdea in the project

@nissy-dev
Copy link
Contributor

Are you talking about BiomeFormatterProvider? if yes, i think it is working. You can use Format code with ⌥⇧ ⌘ L or Ctrl+Alt+L

Thanks! I can confirm it work well

Do you mean format the kotlin code, right? I think we could configure ktLint & ktLintIdea in the project

I didn't mean that I wanted some new setting. All your codes are tab-indented while all others are space-indented, and I just wanted them to be consistent.

I have already applied formatting on my end, so there is nothing in particular that I want you to commit.

Copy link
Contributor

@nissy-dev nissy-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍 Thank you for your patience!  

Copy link
Member

@ematipico ematipico left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's great! I left some comment/question, but we can follow up later with new PRs. I think we can merge it and see how the release goes.

Build and run the plugin requires:

- Java development kit 17+
- IntelliJ IDEA (Ultimate edition or community edition)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that mean that CLion, WebStorm, etc. wouldn't work for local development?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove this requirement,

The Intellij IDEA for testing purpose is automatically downloaded when you run ./gradlew runIde (i don't know if it's possible to use other IDE's)

For more details about IDE Development Instance


### From JetBrains IDEs

- Press `⌘Сmd,` to open the IDE settings and then select Plugins.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Press `⌘Сmd,` to open the IDE settings and then select Plugins.
- Press <kbd title="Cmd">⌘</kbd>, to open the IDE settings and then select Plugins.
  • we should list Ctrl too for windows/linux users
  • I think there's some other key missing, only Cmd doesn't do anything in the IDE.
  • Also, suggesting a different way to render the key on markdown: check how they are rendered here:

Copy link
Contributor Author

@victor-teles victor-teles Sep 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should list Ctrl too for windows/linux users

🪟🪟 Ok

I think there's some other key missing, only Cmd doesn't do anything in the IDE.

It's Cmd + ,

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool. Each key should be wrapped using the tag, it will make things stand out

Comment on lines +27 to +32
## Building and running the plugin

Build and run the plugin requires:

- Java development kit 17+
- IntelliJ IDEA (Ultimate edition or community edition)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is is this required for installing the plugin? I think it's only required for local development. Is there a minimum version for the IntelliJ IDEs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, this requirements are only needed for development, i think we can safely remove this, because it already exists on CONTRIBUTING.md.

About minimum version, the plugin template configure the minimum version to 2023.2, but we can easily change that on gradle.properties file
(Maybe we need to add the plugin version verifier to the github workflow, to ensure the biome plugin binary compatibility)

For more detail about version ranges

Comment on lines +34 to +44
### Running the plugin on IDEA

```shell
./gradlew runIde
```

### Build the plugin

```shell
./gradlew buildPlugin
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these paragraphs needed for the readme?

Comment on lines +3 to +5
pluginGroup = com.github.biomejs.intellijbiome
pluginName = Biome
pluginRepositoryUrl = https://github.com/biomejs/biome
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a documentation page to learn about these properties? I went in https://plugins.jetbrains.com/docs/intellij/intellij-artifacts.html and couldn't find anything about pluginName for example

@ematipico ematipico merged commit e198f1a into biomejs:main Sep 20, 2023
4 checks passed
@victor-teles victor-teles deleted the feature/intellij-lsp-plugin branch September 20, 2023 13:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

📎 IntelliJ Platform LSP
4 participants