Skip to content

Commit

Permalink
Added ARCHITECTURE.md
Browse files Browse the repository at this point in the history
  • Loading branch information
bjansen committed Mar 4, 2021
1 parent 2a59c6c commit fe1d4c4
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 2 deletions.
59 changes: 59 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Plugin architecture

## Build

Gradle is used to build the project. [`gradle-intellij-plugin`][1] is used to pull
any given version of IntelliJ to add its JARs to the classpath, build forms,
publish to the marketplace etc.

GitHub Actions are used for continuous integration, see files in `.github/workflows`.

## Lexing/parsing

An ANTLR v4 grammar in `src/main/antlr` is used to generate a lexer/parser.
`ANTLRv4ParserDefinition` uses the [`antlr4-intellij-adaptor` library][2] to
delegate parsing/lexing to these generated classes.

Syntax highlighting is also using the generated lexer (by delegation) in
`org.antlr.intellij.plugin.ANTLRv4SyntaxHighlighter.getHighlightingLexer`.

## Error checking

The plugin embeds a complete version of ANTLR v4. To highlight warnings in the
editor, the file is parsed again in `ANTLRv4ExternalAnnotator`, but this time
using the "official" parser. The annotator constructs a `org.antlr.v4.Tool`
with all the flags configured in the `Configure ANTLR...` dialog.
`GrammarIssuesCollector` sets up an error listener, then processes all the issues
reported by the `Tool` to show them in the editor.

## Preview window

Contrary to ANTLRWorks, the IntelliJ plugin does not run the actual generated
parser to test a grammar. Instead, it uses [ANTLR interpreters][3]. This is
mainly because the IDE classpath and the project classpath are totally different,
meaning generated parsers and their custom code and dependencies are not
available from the IDE process.

The interpreter provides a convenient way to "run" grammars without needing
any generated code. A major drawback of this approach is that custom code will
not be executed: `@members`, actions, predicates...

The entry point for the preview window is `PreviewPanel`, which holds the main
Swing component displayed in the tool window. It uses `ANTLRv4PluginController`
to maintain a cache of parsed grammars that can be previewed. Everytime the
editor switches to another .g4 grammar, the preview is updated accordingly:
the input text and selected rule are restored to their previous state (if any),
and the interpreter results are updated. Interpreter results include profiling
data, a list of tokens and a tree of matched rules and terminal nodes (both
in graphical form and in JTree form).

`PreviewPanel` acts as an orchestrator between inputs (grammar changed event,
input text changed event) and outputs (profiler, token list, parse tree etc.).

Since the preview panel has full control over the interpreter, it can monitor
the parsing phase to detect potential infinite loops caused by bad grammars,
thus preventing IDE freezes or OutOfMemoryExceptions.

[1]: https://github.com/JetBrains/gradle-intellij-plugin
[2]: https://github.com/antlr/antlr4-intellij-adaptor/
[3]: https://github.com/antlr/antlr4/blob/master/doc/interpreters.md
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,14 @@ Even when a grammar is getting a single interpretation of the input, we often wo

![Live preview](images/color-prefs.png)

# Build notes
# Contributing

We [moved to Gradle](https://github.com/antlr/intellij-plugin-v4/pull/295) for 1.9. To contribute to the project, you need a recent version of IntelliJ IDEA (either Community or Ultimate) with the `Gradle` and `Plugin DevKit` plugins enabled. Use `File > Open` and select the `build.gradle` file to import the project. Once everything is imported, you can run a sandboxed IDE using the `runIde` task, either from the `Gradle` tool window of from the CLI:
We [moved to Gradle](https://github.com/antlr/intellij-plugin-v4/pull/295) for 1.9. To contribute to the project,
you need a recent version of IntelliJ IDEA (either Community or Ultimate) with the `Gradle` and `Plugin DevKit`
plugins enabled.

Use `File > Open` and select the `build.gradle` file to import the project. Once everything is imported, you can run a
sandboxed IDE using the `runIde` task, either from the `Gradle` tool window of from the CLI:

```
cd ~/antlr/code/intellij-plugin-v4
Expand All @@ -183,3 +188,5 @@ cd ~/antlr/code/intellij-plugin-v4
To launch unit tests, run `./gradlew check`.

To build a zipped version of the plugin and its dependencies, run `./gradlew buildPlugin`.

A high level description of how the plugin works can be found in `ARCHITECTURE.md`.

0 comments on commit fe1d4c4

Please sign in to comment.