Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How We Support New Technologies, Languages, a...

How We Support New Technologies, Languages, and Frameworks in IntelliJ IDEA

Many developers, sooner or later, come to a point where they realize none of the existing tools can do exactly what they want. For example, the vendor of your favorite IDE has not implemented a feature you are using, or you are working with a rather new custom framework that isn't yet supported by your IDE. What to do? The good news is that IntelliJ IDEA and its plugins are not set in stone, so anyone yes, that includes you can implement support for a new language, library, or framework.

Yuriy Artamonov

February 25, 2021
Tweet

More Decks by Yuriy Artamonov

Other Decks in Programming

Transcript

  1. Author ▪ Developing libraries, frameworks, and tools for developers for

    the past 10 years ▪ Sad about their imperfect IDE support ▪ Working in IntelliJ IDEA team on features for new technologies 2
  2. Plan 1. IntelliJ IDEA Plugin System 2. Code Insight and

    Frameworks (Spring Framework) 3. Custom Languages (JSONPath) 4. Integration with External Tools (Swagger, JSONPath) 5. Useful Resources 3
  3. Motivation ▪ Almost every company has: in-house frameworks, libraries, code

    style, processes and conventions. ▪ At the same time — we all have routine tasks and it is inevitable. 4
  4. How to deal with the routine ▪ Build more languages

    and frameworks! ▪ Generate more code! ▪ Improve tooling - IDE 5
  5. IntelliJ IDEA Plugin Capabilities ★ Languages and file formats ★

    Static analysis on the fly ★ Navigation ★ Editor improvements ★ Refactoring and code generation ★ Integration with tools and services ★ Code migrations 7
  6. IDE Internals ▪ Services ▪ Virtual File System (VFS) ▪

    Languages - Parsing, Highlighting (PSI) ▪ Editor ▪ Inspection engine ▪ Indexes ▪ Background Processes ▪ UI Library ▪ Extension Points IntelliJ Platform IDEA CE (Java, Groovy, Kotlin) PHP Support Ruby Support IDEA Ultimate PHP Storm RubyMine 8
  7. Plugin System All JetBrains IDEs consist of plugins: 1. Every

    plugin implements extension points of IDE and may declare their own 2. Plugins may depend on platform modules and plugins 9 Groovy Plugin Java Plugin Properties Plugin Ultimate Modules optional
  8. Getting Started 10 1. Check/Enable Plugin DevKit 2. Create a

    Gradle project with IntelliJ Platform Plugin preset 3. Declare and implement extension points Kotlin recommended! (but not required)
  9. Plugin Structure .../resources/META-INF/plugin.xml <idea-plugin> <id>spring-intellij-plugin</id> <name>Spring Framework Support</name> <description><![CDATA[ Provides

    support for Spring Framework for JVM languages ]]></description> <depends>com.intellij.modules.java</depends> <extensions defaultExtensionNs="com.intellij"> <!-- Add your extensions here → </extensions> <actions> <!-- Add your actions here → </actions> </idea-plugin> 12 Metadata Source Code Build Script
  10. Extension Points ▪ Lots of them: action, inspection, intention action,

    reference contributor, ui settings group, language parser, language formatter, etc. ▪ Register them in XML config – plugin.xml ▪ Check also: LangExtensionPoints.xml, PlatformExtensionPoints.xml, VcsExtensionPoints.xml, etc. Example: Groovy support - plugin of IntelliJ IDEA > 1300 lines in plugin.xml. github.com/JetBrains/intellij-community 13
  11. Let’s Improve Something Imagine: we have developed a framework that

    is very similar to Spring Framework. What can go wrong? 16
  12. Implicit Usages Problem: frameworks are powerful and they love implicit

    conventions. @Controller class WelcomeController { @GetMapping("/welcome") public String welcome() { return "Nice to meet you!"; } } 💡 Class ‘WelcomeController’ is never used. 17 Let’s teach IDE to understand those implicit usages!
  13. Implicit Usage Provider There is an extension point for that:

    <implicitUsageProvider implementation="demo.SpringImplicitUsageProvider"/> class SpringImplicitUsageProvider : ImplicitUsageProvider { override fun isImplicitWrite(element: PsiElement): Boolean { TODO() } override fun isImplicitRead(element: PsiElement): Boolean { TODO() } override fun isImplicitUsage(element: PsiElement): Boolean { TODO() } } 18
  14. Syntax Trees PSI - Program Structure Interface, a special representation

    of the program: ▪ Syntax structure of files ▪ Includes semantics and provides resolve procedure ▪ Everything (almost) is represented by PsiElement ▪ Languages provide their own PSI elements 19 PsiFile PsiElement PsiElement PsiElement PsiElement PSI Tree
  15. Java PSI Model Key Elements: ▪ PsiJavaFile ▪ PsiImportList ▪

    PsiClass ▪ PsiAnnotation ▪ PsiField ▪ PsiMethod ▪ ... Check Tools - View PSI Structure of Current File 20
  16. Inspections ▪ Perform static analysis on the fly ▪ Traverse

    PSI tree ▪ Can provide automatic fixes See LocalInspectionTool LocalQuickFix 21
  17. Enforce coding conventions Register extension point: <localInspection language="JAVA" displayName="@Autowired on

    a field in Spring beans" groupName="Spring" enabledByDefault="true" implementationClass="demo.SpringAutowiredInspection"/> Inspection class: class SpringAutowiredInspection : AbstractBaseJavaLocalInspectionTool() { override fun checkMethod(method: PsiMethod, manager: InspectionManager, isOnTheFly: Boolean) : Array<ProblemDescriptor>? { // check here return ProblemDescriptor.EMPTY_ARRAY } } 22
  18. References in PSI ▪ Establish connection between PsiElement usages and

    its declaration: usage ➜ declaration ▪ Can provide auto completion variants ▪ Plugins can contribute new references to existing languages! See PsiReferenceContributor PsiLanguageInjectionHost 23
  19. Property References In Spring @Value annotation supports property interpolation from

    application.properties via expressions ${some.property-name}: @Value("${datasources.default.url}") private String datasourceUrl; Idea: let’s connect these usages with property! 24
  20. Find Usages and Rename Refactoring 1. Find elements with the

    same text 2. Try to find references 3. Match references with PsiElement Works automatically if text of element and references is the same! Customize search of elements with Searcher, ReferenceSearcher. 25
  21. Custom Languages IntelliJ Platform is a powerful platform for building

    development tools targeting any language. Language Support Plan: 1. File and Language Definition 2. Grammar 3. Lexer and Parser 4. Highlighting 5. Completion 6. Inspections 7. Refactorings 27
  22. Grammar-Kit Additional plugin for IntelliJ IDEA: ▪ Provides support for

    BNF Grammars and JFlex lexers editor. ▪ Generates Lexer by BNF. ▪ Generates readable parser/PSI code generator. Must read: https://plugins.jetbrains.com/docs/intellij/custom-language-support.html 28
  23. Language Injection Language injections let you work with pieces of

    code in other languages embedded in your code. Any language can be injected to any other language! 29
  24. Language Injections in Real Life ▪ Regexp ▪ SQL ▪

    JSON ▪ XML & HTML ▪ XPath / JSONPath ▪ JavaScript ▪ ... 30
  25. How to Integrate External Tools 1. Just works: Settings -

    External Tools 2. Easy: find JVM library that implements integration: (Gradle API, Docker Java, Swagger Codegen) 3. Harder: connect to external API via network or UNIX-socket (Spring Initializr, Java Debugger) 4. Pain and Suffering: run command line tools (Git, Docker, NPM) 5. Web Content 31
  26. UI Development ▪ Java Swing + Kotlin UI DSL plugins.jetbrains.com/

    docs/intellij/kotlin-ui-dsl.html ▪ Integrated Web Content with JCEF 33
  27. Web Content JCEF - Java Chromium Embedded Framework https://plugins.jetbrains.com/docs/intellij/jcef.html Embedding

    of the browser component inside the IDE allows amongst others: ▪ Rendering HTML content ▪ Previewing generated HTML (e.g., from Markdown or Swagger UI) 34
  28. Sometimes It Takes a Lot of Effort Spring Framework Support

    in numbers: ▪ 260k LOC Java ▪ 20k LOC Kotlin ▪ 350k LOC Total ▪ 3500 Tests 35
  29. Useful Resources ▪ Examples from the Talk: github.com/jreznot/intellij-plugin-showcase ▪ Source

    Code of IntelliJ IDEA CE: github.com/JetBrains/intellij-community ▪ Plugin DevKit Documentation: jetbrains.org/intellij/sdk/docs/basics.html ▪ JetBrains Platform Slack: plugins.jetbrains.com/slack 37