Skip to content
This repository has been archived by the owner on May 16, 2022. It is now read-only.

Latest commit

 

History

History
126 lines (95 loc) · 8.28 KB

CONTRIBUTING.md

File metadata and controls

126 lines (95 loc) · 8.28 KB

Contribution guide

Thank you for your interest in contributing to Kotlin!

This guide explains the contribution process established in the Kotlin IntelliJ IDEA plugin, as well as defines requirements for the changes. Please read the document carefully before submitting requests.

Here are links to other related projects you might want to contribute to:

Contents

  1. How to contribute
  2. What to contribute
  3. Pull request requirements
  4. Writing intentions/inspections

1. How to contribute

You can contribute to the plugin by sending us a Pull Request to the master branch.

Because of technical reasons, we can't use the Github UI for accepting PRs. Instead, we pick commits manually. Don't worry: we won't change the commits (except maybe trivial changes such as typos) or its author information.

You will likely need to set up a project locally to modify its code. The detailed setup instructions are available in the README.

To learn how to write plugins for IntelliJ IDEA, please refer to the IntelliJ Platform SDK DevGuide. The portal contains a lot of useful information and explains how the IDE works under-the-hood.

There's also a #kontributors channel in the public Slack. Please feel free to ask questions regarding contributions to the Kotlin IntelliJ IDEA plugin.

2. What to contribute

An excellent way to contribute would be to fix some of the issues marked with the "up-for-grabs" tag. They usually don't take a lot of time to be fixed, and the fix is often local.

If you plan to work on new functionality (new intentions, inspections and so on) or want to fix something by re-writing a significant part of a subsystem, please contact us beforehand via the #kontributors channel on Slack. Our experience shows that features that seem trivial often require thorough design work, or implementing them might dramatically affect the performance of the whole IDE. So we might not be able to accept the Pull Request, even if it brings significant value to the users.

Surely, this doesn't mean we say no to arbitrary changes. However, the review process might be slightly longer than usual. So sticking to the "up-for-grabs" tag is a safe way to go.

3. Pull Request requirements

We have several requirements for the Pull Requests:

  1. A Pull Request must solve some issue. So the issue identifier must be specified.
    We use KT and KTIJ projects on YouTrack. If the issue doesn't exist yet, please create it in KTIJ.
  2. Do not submit Pull Requests that solve multiple issues that aren't interconnected. Create several PRs instead.
  3. The plugin must still work after the change. Please ensure the plugin compiles and runs successfully after the change.
  4. Each non-trivial change in plugin functionality must come with tests, so add new tests or adapt existing ones. In both cases, please ensure the existing tests don't fail with the PR applied.
  5. Avoid merge commits. If you want to adapt your PR after changes in master, use git pull --rebase instead.

4. Writing intentions/inspections

This section contains tips that might help you to write a

4.1. IntelliJ IDEA

You can find necessary information about how to write inspections, intentions and quick fixes in the Code Inspections tutorial.

It's essential to know about PSI, the source code model used in IntelliJ IDEA. To inspect PSI, you can use either the built-in Psi Viewer available in the "internal" mode or an external plugin called PsiViewer.

4.2. Kotlin-specific information

General information

  1. Intentions and inspections must be registered in idea/resources/META-INF/inspections.xml.
  2. There must be a description in English. Put descriptions for intentions to idea/resources-en/intentionDescriptions, descriptions for inspections are in idea/resources-en/inspectionDescriptions.
  3. All intentions, inspections and quick-fixes should have automatic tests. Put test data for local inspections with quick fixes to idea/testData/inspectionsLocal, inspections without quick fixes to idea/testData/inspections.
  4. Prefer inspections with ProblemHighlightType.INFORMATION and attached quick-fixes over intentions.
  5. In inspection code, use only ProblemHighlightType.GENERIC_ERROR_OR_WARNING as it allows users to adjust the inspection level by themselves.
  6. Make the inspection highlighting range as narrow as possible. E.g. highlight only the class name instead of the whole class declaration, and a called function name instead of the whole call.
  7. Never hard-code strings displayed to the user in code. Use language bundles instead. See the KotlinBundle as an example.
  8. You can test the exception on the kotlin-ide project itself. To do it, clone kotlin-ide to some other directory (or create a Git worktree), run the "IDEA" run configuration, open the cloned project in it and run your inspection using the "Run Inspection by Name" action.
    Here's a short check list:
    • Check that you didn't introduce performance issues by monitoring execution time;
    • Check if memory consumption is reasonable;
    • Check false positives (or maybe false negatives);
    • Try to apply quick fixes and check if code is correct.

Reference resolution

  1. Resolution operations (analyze(), resolveToCall(), resolveToDescriptors() etc.) are expensive. Perform checks that don't depend on resolution first. For instance, if your inspection looks for top-level classes annotated with @Foo, check if the current declaration is a top-level class before resolving the Foo reference.
  2. Avoid using resolveToDesciptor() unless necessary as it throws an exception if the reference can't be resolved. Use resolveToDescriptorIfAny() instead.
  3. If you need to resolve several references at once, call analyze() on a common PsiElement and then fetch results for individual references from the received BindingContext. Calling resolveToDescriptorIfAny() or resolveToCall() several times may lead to inconsistent results.
  4. Don't depend too much on applicability checks. Code could have changed since their execution. Check the required pre-conditions once more before code modification.
  5. Use the languageVersionSettings extension property to get LanguageVersionSettings for a particular PsiElement.

Performance and stability tips

  1. Never do anything continuous in the UI thread. Never call resolve() from it.
  2. Always start potentially long operations (such as "Usages search") under a ProgressIndicator so the user can cancel it if needed.
  3. Access PSI, module and project components only from a read/write action.
  4. Use SmartPsiElementPointer to store references to PsiElements across multiple read/write actions. IntelliJ IDEA might dispose or replace a PsiElement between the actions.
  5. Do not store any references to PSI or a project structure statically or in long-living project components. It will surely lead to memory leaks. If absolutely necessary, use SmartPsiElementPointer (and corresponding createSmartPointer()).