Compare commits
No commits in common. "master" and "16.0.0-pre2" have entirely different histories.
master
...
16.0.0-pre
482 changed files with 15475 additions and 21595 deletions
43
.gitattributes
vendored
43
.gitattributes
vendored
|
@ -1,44 +1 @@
|
||||||
* text=auto eol=lf
|
* text=auto eol=lf
|
||||||
|
|
||||||
*.[jJ][aA][rR] binary
|
|
||||||
|
|
||||||
*.[pP][nN][gG] binary
|
|
||||||
*.[jJ][pP][gG] binary
|
|
||||||
*.[jJ][pP][eE][gG] binary
|
|
||||||
*.[gG][iI][fF] binary
|
|
||||||
*.[tT][iI][fF] binary
|
|
||||||
*.[tT][iI][fF][fF] binary
|
|
||||||
*.[iI][cC][oO] binary
|
|
||||||
*.[sS][vV][gG] text
|
|
||||||
*.[eE][pP][sS] binary
|
|
||||||
*.[xX][cC][fF] binary
|
|
||||||
|
|
||||||
*.[kK][aA][rR] binary
|
|
||||||
*.[mM]4[aA] binary
|
|
||||||
*.[mM][iI][dD] binary
|
|
||||||
*.[mM][iI][dD][iI] binary
|
|
||||||
*.[mM][pP]3 binary
|
|
||||||
*.[oO][gG][gG] binary
|
|
||||||
*.[rR][aA] binary
|
|
||||||
|
|
||||||
*.7[zZ] binary
|
|
||||||
*.[gG][zZ] binary
|
|
||||||
*.[tT][aA][rR] binary
|
|
||||||
*.[tT][gG][zZ] binary
|
|
||||||
*.[zZ][iI][pP] binary
|
|
||||||
|
|
||||||
*.[tT][cC][nN] binary
|
|
||||||
*.[sS][oO] binary
|
|
||||||
*.[dD][lL][lL] binary
|
|
||||||
*.[dD][yY][lL][iI][bB] binary
|
|
||||||
*.[pP][sS][dD] binary
|
|
||||||
*.[tT][tT][fF] binary
|
|
||||||
*.[oO][tT][fF] binary
|
|
||||||
|
|
||||||
*.[pP][aA][tT][cC][hH] -text
|
|
||||||
|
|
||||||
*.[bB][aA][tT] text eol=crlf
|
|
||||||
*.[cC][mM][dD] text eol=crlf
|
|
||||||
*.[pP][sS]1 text eol=crlf
|
|
||||||
|
|
||||||
*[aA][uU][tT][oO][gG][eE][nN][eE][rR][aA][tT][eE][dD]* binary
|
|
100
.gitignore
vendored
100
.gitignore
vendored
|
@ -1,5 +1,93 @@
|
||||||
# Created by https://www.toptal.com/developers/gitignore/api/gradle,java
|
# Created by https://www.toptal.com/developers/gitignore/api/intellij+all,gradle,java
|
||||||
# Edit at https://www.toptal.com/developers/gitignore?templates=gradle,java
|
# Edit at https://www.toptal.com/developers/gitignore?templates=intellij+all,gradle,java
|
||||||
|
|
||||||
|
### Intellij+all ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
.idea/**/aws.xml
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
.idea/artifacts
|
||||||
|
.idea/compiler.xml
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
.idea/modules.xml
|
||||||
|
.idea/*.iml
|
||||||
|
.idea/modules
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
.idea/sonarlint/
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
### Intellij+all Patch ###
|
||||||
|
# Ignore everything but code style settings and run configurations
|
||||||
|
# that are supposed to be shared within teams.
|
||||||
|
|
||||||
|
.idea/*
|
||||||
|
|
||||||
|
!.idea/codeStyles
|
||||||
|
!.idea/runConfigurations
|
||||||
|
|
||||||
### Java ###
|
### Java ###
|
||||||
# Compiled class file
|
# Compiled class file
|
||||||
|
@ -54,11 +142,9 @@ gradle-app.setting
|
||||||
# Java heap dump
|
# Java heap dump
|
||||||
*.hprof
|
*.hprof
|
||||||
|
|
||||||
# End of https://www.toptal.com/developers/gitignore/api/gradle,java
|
# End of https://www.toptal.com/developers/gitignore/api/intellij+all,gradle,java
|
||||||
|
|
||||||
.idea
|
|
||||||
.intellijPlatform
|
|
||||||
jbr
|
jbr
|
||||||
secrets
|
secrets
|
||||||
!**/src/**/build/
|
.idea/runConfigurations/*.xml
|
||||||
.kotlin
|
.intellijPlatform
|
92
.idea/codeStyles/Project.xml
generated
Normal file
92
.idea/codeStyles/Project.xml
generated
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<code_scheme name="Project" version="173">
|
||||||
|
<JavaCodeStyleSettings>
|
||||||
|
<option name="ANNOTATION_PARAMETER_WRAP" value="2" />
|
||||||
|
<option name="ALIGN_MULTILINE_ANNOTATION_PARAMETERS" value="true" />
|
||||||
|
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99999" />
|
||||||
|
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99999" />
|
||||||
|
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
|
||||||
|
<value />
|
||||||
|
</option>
|
||||||
|
<option name="IMPORT_LAYOUT_TABLE">
|
||||||
|
<value>
|
||||||
|
<package name="" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="net.minecraft" withSubpackages="true" static="false" />
|
||||||
|
<package name="net.minecraftforge" withSubpackages="true" static="false" />
|
||||||
|
<package name="cpw" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="javax" withSubpackages="true" static="false" />
|
||||||
|
<package name="java" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="" withSubpackages="true" static="true" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="JD_ADD_BLANK_AFTER_PARM_COMMENTS" value="true" />
|
||||||
|
<option name="JD_ADD_BLANK_AFTER_RETURN" value="true" />
|
||||||
|
</JavaCodeStyleSettings>
|
||||||
|
<JetCodeStyleSettings>
|
||||||
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
|
</JetCodeStyleSettings>
|
||||||
|
<ScalaCodeStyleSettings>
|
||||||
|
<option name="MULTILINE_STRING_CLOSING_QUOTES_ON_NEW_LINE" value="true" />
|
||||||
|
</ScalaCodeStyleSettings>
|
||||||
|
<codeStyleSettings language="Glsl">
|
||||||
|
<option name="SPACE_BEFORE_COLON" value="false" />
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="JAVA">
|
||||||
|
<option name="KEEP_LINE_BREAKS" value="false" />
|
||||||
|
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
|
||||||
|
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false" />
|
||||||
|
<option name="ALIGN_MULTILINE_CHAINED_METHODS" value="true" />
|
||||||
|
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
|
||||||
|
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
|
||||||
|
<option name="ALIGN_MULTILINE_ASSIGNMENT" value="true" />
|
||||||
|
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
|
||||||
|
<option name="ALIGN_MULTILINE_METHOD_BRACKETS" value="true" />
|
||||||
|
<option name="ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION" value="true" />
|
||||||
|
<option name="ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION" value="true" />
|
||||||
|
<option name="CALL_PARAMETERS_WRAP" value="1" />
|
||||||
|
<option name="RESOURCE_LIST_WRAP" value="1" />
|
||||||
|
<option name="EXTENDS_LIST_WRAP" value="1" />
|
||||||
|
<option name="THROWS_LIST_WRAP" value="1" />
|
||||||
|
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
|
||||||
|
<option name="THROWS_KEYWORD_WRAP" value="1" />
|
||||||
|
<option name="METHOD_CALL_CHAIN_WRAP" value="5" />
|
||||||
|
<option name="BINARY_OPERATION_WRAP" value="1" />
|
||||||
|
<option name="TERNARY_OPERATION_WRAP" value="1" />
|
||||||
|
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
|
||||||
|
<option name="KEEP_SIMPLE_LAMBDAS_IN_ONE_LINE" value="true" />
|
||||||
|
<option name="FOR_STATEMENT_WRAP" value="1" />
|
||||||
|
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
|
||||||
|
<option name="ASSIGNMENT_WRAP" value="1" />
|
||||||
|
<option name="ASSERT_STATEMENT_WRAP" value="1" />
|
||||||
|
<option name="ASSERT_STATEMENT_COLON_ON_NEXT_LINE" value="true" />
|
||||||
|
<option name="IF_BRACE_FORCE" value="3" />
|
||||||
|
<option name="DOWHILE_BRACE_FORCE" value="3" />
|
||||||
|
<option name="WHILE_BRACE_FORCE" value="3" />
|
||||||
|
<option name="FOR_BRACE_FORCE" value="3" />
|
||||||
|
<option name="PARAMETER_ANNOTATION_WRAP" value="1" />
|
||||||
|
<option name="VARIABLE_ANNOTATION_WRAP" value="5" />
|
||||||
|
<option name="ENUM_CONSTANTS_WRAP" value="2" />
|
||||||
|
<option name="WRAP_ON_TYPING" value="0" />
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="JavaScript">
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="2" />
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||||
|
<option name="TAB_SIZE" value="2" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="TypeScript">
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="2" />
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||||
|
<option name="TAB_SIZE" value="2" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="kotlin">
|
||||||
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
|
</codeStyleSettings>
|
||||||
|
</code_scheme>
|
||||||
|
</component>
|
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||||
|
</state>
|
||||||
|
</component>
|
483
CHANGELOG.md
483
CHANGELOG.md
|
@ -17,489 +17,6 @@ Changelog structure reference:
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
## [25.2.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Debugger
|
|
||||||
- Notify the user if zig run / zig test debugging starts, but a build.zig is present
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- Line marker task suggestions for main/test now defer to Zig Build if build.zig file is detected.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Debugger
|
|
||||||
- Compilation failures did not open the terminal properly and suppressed the error message
|
|
||||||
|
|
||||||
## [25.1.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- IDEA 2025.1 support
|
|
||||||
|
|
||||||
- LSP
|
|
||||||
- Configurable inlay hints file size limit to reduce IDE lag
|
|
||||||
|
|
||||||
## [25.0.2]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- ZLS settings not scrollable in the language server list
|
|
||||||
|
|
||||||
## [25.0.1]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- Zig.iml file created in every project
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- BREAKING MAJOR UPDATE: Fully reworked toolchain and language server management
|
|
||||||
The configuration menu is now very similar to the intellij java toolchain management,
|
|
||||||
with proper toolchain selection, detection, downloading, etc. This change will require
|
|
||||||
you to re-configure your toolchains!
|
|
||||||
- Zig external library root is now no longer shown if zig is not configured
|
|
||||||
|
|
||||||
## [24.0.1]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Project, Debugging
|
|
||||||
- TTY support for zig processes
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- "Emulate terminal" and "colored output" config options have been removed from zig run/test/build tasks, as they are no longer required for ZigBrains to work.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Debugger
|
|
||||||
- Build errors didn't get shown in the console
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- File path browse buttons in zig run configurations didn't work
|
|
||||||
- Occasional GUI deadlocks
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- IPC wrapper wasn't passing exit code
|
|
||||||
|
|
||||||
## [23.1.2]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- LSP
|
|
||||||
- IDE warning when renaming symbols
|
|
||||||
|
|
||||||
## [23.1.1]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- New project creation creates a blank ZLS config
|
|
||||||
|
|
||||||
## [23.1.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- Support running file main/tests with hotkey (default: ctrl+shift+f10)
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Direnv
|
|
||||||
- Centralized all direnv toggling into a single project-level option
|
|
||||||
|
|
||||||
## [23.0.2]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Documentation comment after regular comment was being highlighted as regular comment
|
|
||||||
|
|
||||||
## [23.0.1]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- mkfifo/bash for zig progress visualization is now detected more reliably (fixes error on macOS)
|
|
||||||
- Deadlock when launching zig build tasks
|
|
||||||
|
|
||||||
## [23.0.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- Zig std.Progress visualization in the zig tool window (Linux/macOS only)
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- Executable / Library new project templates temporarily removed until zig stabilizes
|
|
||||||
|
|
||||||
## [22.0.1]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- LSP
|
|
||||||
- Changing ZLS configs would not restart ZLS
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- Occasional "AWT events are not allowed inside write action" error coming from LSP
|
|
||||||
- IllegalStateException coming from the standard library handler
|
|
||||||
|
|
||||||
## [22.0.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- LSP
|
|
||||||
- Error/Warning banner at the top of the editor when ZLS is misconfigured/not running
|
|
||||||
- ZLS version indicator in the zig settings
|
|
||||||
|
|
||||||
- Toolchain
|
|
||||||
- More descriptive error messages when toolchain detection fails
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- !!BREAKING CHANGE!! Changed file format of zig tasks to store command line arguments as strings instead of string lists.
|
|
||||||
This (and newer) versions of the plugin will automatically upgrade tasks from 21.1.0 and before.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Debugging
|
|
||||||
- Breakpoints could not be placed inside zig code in Android Studio
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- Zig run/debug configuration command line arguments would lose quotes around arguments
|
|
||||||
|
|
||||||
## [21.1.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Zon
|
|
||||||
- ZLS integration
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Zon
|
|
||||||
- Fully refactored the parser for parity with the zig parser
|
|
||||||
|
|
||||||
## [21.0.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Changing the zig standard library path in the project settings now properly updates the dependency
|
|
||||||
- ZLS
|
|
||||||
- All of the config options are now exposed in the GUI
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- New project panel is now much more compact
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- `zig env` failure causes an IDE error
|
|
||||||
- A local toolchain disappearing (std directory or zig exe deleted) is now handled properly
|
|
||||||
|
|
||||||
## [20.3.0]
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Improved default colors
|
|
||||||
|
|
||||||
## [20.2.2]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Debugging
|
|
||||||
- `zig build run` would run the process twice, one without, one with debugging
|
|
||||||
|
|
||||||
## [20.2.1]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Lexer error when a zig file has a comment or multiline string at the end of file without trailing newline
|
|
||||||
|
|
||||||
## [20.2.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Live template support
|
|
||||||
|
|
||||||
## [20.1.3]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- `.zig-cache` directory added to autogenerated gitignore in the project generator
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- Zig Build tool window crashes when opening remote projects
|
|
||||||
|
|
||||||
## [20.1.2]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Source file path highlighter made the terminal lag with some files
|
|
||||||
- Non-terminating rule in lexer could make the editor hang
|
|
||||||
|
|
||||||
## [20.1.1]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Unterminated string at the end of the file soft-locks the editor
|
|
||||||
- Trailing commas in for loop parameters don't get parsed correctly
|
|
||||||
|
|
||||||
## [20.1.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- String, character literal, and `@"identifier"` quote matching
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Zon
|
|
||||||
- Broken string quote handling
|
|
||||||
|
|
||||||
## [20.0.4]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Renamed Zig new file task to "Zig File" and moved to the file creation group
|
|
||||||
|
|
||||||
## [20.0.3]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- "Save all documents" hanging when trying to run a zig file
|
|
||||||
|
|
||||||
## [20.0.2]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Escape sequence highlighting in char literals
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- Direnv now only runs automatically in trusted projects
|
|
||||||
- Toolchain autodetection is now done in the background on project load
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Unicode characters in char literals triggered an error
|
|
||||||
|
|
||||||
## [20.0.1]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- IDE freezes when opening a zig project / doing zig init
|
|
||||||
- Test tasks don't work and try to run the file as an executable
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Struct fields being styled as static fields instead of instance fields
|
|
||||||
|
|
||||||
## [20.0.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Debugging
|
|
||||||
- Progress indicator while zig is compiling the debuggable exe
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- The entire plugin has been re-implemented in Kotlin
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Most of the internals have been rewritten to be fully asynchronous, so freezes should happen way less
|
|
||||||
|
|
||||||
## [19.3.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Toolchains, Run Configurations
|
|
||||||
- [Direnv](https://github.com/direnv/direnv) support
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Missing description for string conversion intentions
|
|
||||||
|
|
||||||
## [19.2.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Enter key handling in strings and multi line strings
|
|
||||||
- Intentions for converting between multi line and quoted strings
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Multiline string language injections broke when editing the injected text
|
|
||||||
|
|
||||||
## [19.1.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Language injections in strings
|
|
||||||
- Syntax highlighting for escape sequences in strings
|
|
||||||
|
|
||||||
- LSP
|
|
||||||
- Option to toggle inlay hints on/off
|
|
||||||
- Compacted error{...} blocks in inlay hints
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Runner
|
|
||||||
- The process execution pipeline is now fully asynchronous
|
|
||||||
- Error output is no longer redirected to standard output
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Debugger
|
|
||||||
- Zig compilation will no longer cause IDE freezes
|
|
||||||
- Debugging with GDB no longer causes internal IDE warnings
|
|
||||||
- Debugging `zig run` configurations is now possible
|
|
||||||
- LSP
|
|
||||||
- Rare error when checking LSP presence
|
|
||||||
- No more error spam when zig or zls binary is missing
|
|
||||||
|
|
||||||
## [18.0.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Labeled switch statements
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- LSP
|
|
||||||
- Updated to LSP4IJ 0.7.0
|
|
||||||
|
|
||||||
## [17.3.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Structure view
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- LSP
|
|
||||||
- Updated to LSP4IJ 0.6.0
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- CLion will no longer prompt you to import zig projects as CMake
|
|
||||||
|
|
||||||
## [17.2.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- IDEA 2024.3 support
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- Safer standard library path resolution
|
|
||||||
|
|
||||||
## [17.1.0]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- Relative paths in zig toolchain configuration would break the entire IDE
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
|
|
||||||
- ZLS
|
|
||||||
- Obsolete config options which are no longer used since migrating to LSP4IJ
|
|
||||||
|
|
||||||
## [17.0.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- Zig Build integrated into an IDE tool window. Currently only supports running single steps, for more complex steps,
|
|
||||||
create a custom build configuration as before.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- Increased internal zig tool timeout to 10 seconds. Note that tasks don't have timeout, this is only used for
|
|
||||||
ZigBrains getting metadata about the compiler and the buildscript.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Project
|
|
||||||
- Toolchain working directory was not set when requesting compiler metadata
|
|
||||||
|
|
||||||
## [16.1.3]
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Debugger (Windows)
|
|
||||||
- MSVC debugger metadata download now requires consent from the user
|
|
||||||
- Metadata download is now cached after the first fetch
|
|
||||||
- Metadata download timeout has been set to 3 seconds, after which it reverts to the fallback file
|
|
||||||
|
|
||||||
## [16.1.2]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Comptime struct fields not being parsed properly
|
|
||||||
|
|
||||||
## [16.1.1]
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Zig
|
|
||||||
- Standard library override always auto-enabling
|
|
||||||
- Better toolchain autodetect
|
|
||||||
|
|
||||||
- ZLS
|
|
||||||
- Better language server autodetect
|
|
||||||
|
|
||||||
## [16.1.0]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Zon
|
|
||||||
- Support for .lazy dependency property
|
|
||||||
- Comment/uncomment hotkey support
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Zon
|
|
||||||
- More reliable autocomplete
|
|
||||||
|
|
||||||
## [16.0.0]
|
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Debugger
|
- Debugger
|
||||||
|
|
19
CONTRIBUTING.md
Normal file
19
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
For now this project is still pretty small, but here are some general guidelines on how to contribute to this repository
|
||||||
|
|
||||||
|
- This project ships with a code style config in .idea, your IDE should automatically apply it when you pull the repo.
|
||||||
|
When making pull requests, please try to keep to this style as much as possible.
|
||||||
|
|
||||||
|
- Use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/), and scope as much as you can.
|
||||||
|
|
||||||
|
- Do not edit the relationship tree between modules without unanimous agreement from the project lead.
|
||||||
|
|
||||||
|
If you want an "upstream" module (for instance, the LSP) receive data from a "downstream" module
|
||||||
|
(for instance, the project module), you should use service providers, dependency injections, or other ways to implement
|
||||||
|
the dataflow in a way where the upstream module is not directly aware of downstream modules.
|
||||||
|
|
||||||
|
The main purpose of this is to avoid any circular dependencies, which could cause proprietary IDE-only features
|
||||||
|
(for instance, the CLion debugger module) to be depended on by FOSS modules. This restriction is non-negotiable.
|
||||||
|
|
||||||
|
- Any complex language inspection, syntax action, or similar, should be done by ZLS, and ZigBrains will just act as an
|
||||||
|
adapter for these features. This notion of "complexity" is determined by the project maintainer. Open an issue
|
||||||
|
that explains the feature before you start implementing anything!
|
40
LICENSE
40
LICENSE
|
@ -1,35 +1,36 @@
|
||||||
|
All code in this project, unless specified differently, is licensed under the Apache 2.0 license.
|
||||||
|
Graphical assets derived from the Zig logo are governed by a different license, included below.
|
||||||
|
--------------------------------
|
||||||
ZigBrains
|
ZigBrains
|
||||||
Copyright (C) 2023-2025 FalsePattern
|
|
||||||
All Rights Reserved
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
Copyright 2023-2024 FalsePattern
|
||||||
in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
you may not use this file except in compliance with the License.
|
||||||
the Free Software Foundation, only version 3 of the License.
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
Unless required by applicable law or agreed to in writing, software
|
||||||
GNU Lesser General Public License for more details.
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
--------------------------------
|
--------------------------------
|
||||||
The following sections are the licenses of code derived from third party projects:
|
The following sections are the licenses of code derived from third party projects:
|
||||||
|
|
||||||
|
--------------------------------
|
||||||
|
The code inside the `lsp` package is derived from the LSP4IntelliJ project, with various modifications, fixes, and
|
||||||
|
additions to fix any outstanding issues i was having with the original code. (https://github.com/ballerina-platform/lsp4intellij)
|
||||||
|
|
||||||
|
The original code is Copyright WSO2 Inc., licensed under the `Apache 2.0` license.
|
||||||
--------------------------------
|
--------------------------------
|
||||||
The art assets inside src/art/zig, and all copies of them, are derived from the official Zig Programming Language logo,
|
The art assets inside src/art/zig, and all copies of them, are derived from the official Zig Programming Language logo,
|
||||||
which are the property of the Zig Software Foundation.
|
which are the property of the Zig Software Foundation.
|
||||||
(https://github.com/ziglang/logo)
|
(https://github.com/ziglang/logo)
|
||||||
These art assets are licensed under Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0).
|
These art assets are licensed under Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0).
|
||||||
--------------------------------
|
--------------------------------
|
||||||
The art assets inside src/art/zls, and all copies of them, are derived from the Zig Language Server,
|
|
||||||
which are the property of the zigtools organization.
|
|
||||||
(https://github.com/zigtools/zls)
|
|
||||||
These art assets are licensed under MIT license.
|
|
||||||
--------------------------------
|
|
||||||
Parts of the codebase are based on the intellij-zig plugin,
|
Parts of the codebase are based on the intellij-zig plugin,
|
||||||
developed by HTGAzureX1212 (https://github.com/HTGAzureX1212), licensed under the Apache 2.0 license.
|
developed by HTGAzureX1212 (https://github.com/HTGAzureX1212), licensed under the Apache 2.0 license.
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
@ -40,7 +41,4 @@ developed by the intellij-rust team (https://github.com/intellij-rust), licensed
|
||||||
All of the licenses listed here are available in the following files, bundled with the plugin:
|
All of the licenses listed here are available in the following files, bundled with the plugin:
|
||||||
- licenses/APACHE_2.0.LICENSE
|
- licenses/APACHE_2.0.LICENSE
|
||||||
- licenses/CC_BY_SA_4.0.LICENSE
|
- licenses/CC_BY_SA_4.0.LICENSE
|
||||||
- licenses/GPL3.LICENSE
|
|
||||||
- licenses/INTELLIJ-RUST.LICENSE
|
- licenses/INTELLIJ-RUST.LICENSE
|
||||||
- licenses/LGPL3.LICENSE
|
|
||||||
- licenses/ZLS.LICENSE
|
|
49
MODULE_TREE.md
Normal file
49
MODULE_TREE.md
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
## What is this?
|
||||||
|
This document describes the relationships between the different "modules" of ZigBrains.
|
||||||
|
|
||||||
|
These relationships are strictly enforced, and modules that do not directly (or indirectly) depend on another
|
||||||
|
module cannot access their classes.
|
||||||
|
|
||||||
|
The primary purpose of this strictly enforced module system is to avoid code compatible with open source IDEs (IDEA/PyCharm Community)
|
||||||
|
from depending on code that only works on proprietary IDEs (IDEA Ultimate/CLion/...).
|
||||||
|
|
||||||
|
NOTE: These "modules" are in no way related to the module system introduced in Java 9. They're just called the same.
|
||||||
|
|
||||||
|
The suffix after the module name signifies which IDE it depends on.
|
||||||
|
|
||||||
|
- IC: IDEA Community
|
||||||
|
- CL: CLion
|
||||||
|
- EXT: External maven library
|
||||||
|
|
||||||
|
IC modules MUST NOT depend on CL modules, as this violates the restrictions set forth above.
|
||||||
|
|
||||||
|
## Modules
|
||||||
|
|
||||||
|
### Common (IC)
|
||||||
|
|
||||||
|
### LSP-Common (IC)
|
||||||
|
- LSP4J (EXT)
|
||||||
|
|
||||||
|
### LSP (IC)
|
||||||
|
- Apache Commons Lang 3 (EXT)
|
||||||
|
- Common (IC)
|
||||||
|
- LSP-Common (IC)
|
||||||
|
|
||||||
|
### Zig (IC)
|
||||||
|
- Grammarkit (EXT)
|
||||||
|
- Common (IC)
|
||||||
|
- LSP (IC)
|
||||||
|
|
||||||
|
### Project (IC)
|
||||||
|
- Common (IC)
|
||||||
|
- Zig (IC)
|
||||||
|
|
||||||
|
### Zon (IC)
|
||||||
|
- Grammarkit (EXT)
|
||||||
|
- Common (IC)
|
||||||
|
|
||||||
|
### Debugger (IU/CL)
|
||||||
|
- Common (IC)
|
||||||
|
- LSP-Common (IC)
|
||||||
|
- Zig (IC)
|
||||||
|
- Project (IC)
|
89
README.md
89
README.md
|
@ -1,10 +1,10 @@
|
||||||
# ZigBrains
|
# ZigBrains
|
||||||
|
|
||||||
Zig language support for IntelliJ IDEA, CLion, and other JetBrains IDEs. Now written in Kotlin!
|
Zig language support for IntelliJ IDEA, CLion, and other JetBrains IDEs.
|
||||||
|
|
||||||
# Installing
|
## Installing
|
||||||
|
|
||||||
You can either install this plugin from the [JetBrains Marketplace](https://plugins.jetbrains.com/plugin/22456-zigbrains), or from [FalsePattern's website](https://falsepattern.com/zigbrains).
|
You can either install this plugin from the [JetBrains Marketplace](https://plugins.jetbrains.com/plugin/22456-zigbrains), or from FalsePattern's [website](https://falsepattern.com/zigbrains).
|
||||||
|
|
||||||
See [the quick setup guide](#quick-setup-guide-for-zig-and-zls) for how to set up language server integration.
|
See [the quick setup guide](#quick-setup-guide-for-zig-and-zls) for how to set up language server integration.
|
||||||
|
|
||||||
|
@ -15,13 +15,52 @@ through the built-in plugin browser:
|
||||||
1. Go to `Settings -> Plugins`
|
1. Go to `Settings -> Plugins`
|
||||||
2. To the right of the `Installed` button at the top, click on the `...` dropdown menu, then select `Manage Plugin Repositories...`
|
2. To the right of the `Installed` button at the top, click on the `...` dropdown menu, then select `Manage Plugin Repositories...`
|
||||||
3. Click the add button, and then enter the ZigBrains updater URL, based on your IDE version:
|
3. Click the add button, and then enter the ZigBrains updater URL, based on your IDE version:
|
||||||
- `2025.1.*` or newer: https://falsepattern.com/zigbrains/updatePlugins-251.xml
|
|
||||||
- `2024.3.*`: https://falsepattern.com/zigbrains/updatePlugins-243.xml
|
|
||||||
- `2024.2.*`: https://falsepattern.com/zigbrains/updatePlugins-242.xml
|
- `2024.2.*`: https://falsepattern.com/zigbrains/updatePlugins-242.xml
|
||||||
- `2024.1.*`: https://falsepattern.com/zigbrains/updatePlugins-241.xml
|
- `2024.1.*`: https://falsepattern.com/zigbrains/updatePlugins-241.xml
|
||||||
|
- `2023.3.*`: https://falsepattern.com/zigbrains/updatePlugins-233.xml
|
||||||
|
- `2023.2.*`: https://falsepattern.com/zigbrains/updatePlugins-232.xml
|
||||||
4. Click `OK`, and your IDE should now automatically detect the latest version
|
4. Click `OK`, and your IDE should now automatically detect the latest version
|
||||||
(both in the Installed tab and in the Marketplace tab), even if it's not yet verified on the official JetBrains marketplace yet.
|
(both in the Installed tab and in the Marketplace tab), even if it's not yet verified on the official JetBrains marketplace yet.
|
||||||
|
|
||||||
|
## Developer guide
|
||||||
|
|
||||||
|
### All platforms
|
||||||
|
|
||||||
|
After importing the gradle project, you need to run the `build setup -> generateSources` tasks.
|
||||||
|
|
||||||
|
### NixOS
|
||||||
|
|
||||||
|
In addition to the generated sources, you also need to run the `build setup -> nixos_jbr` task, otherwise java will
|
||||||
|
complain about missing files
|
||||||
|
|
||||||
|
## Special Thanks
|
||||||
|
|
||||||
|
- The [ZigTools](https://github.com/zigtools/) team for developing the Zig Language Server.
|
||||||
|
|
||||||
|
- [HTGAzureX1212](https://github.com/HTGAzureX1212) for developing [intellij-zig](https://github.com/intellij-zig/intellij-zig),
|
||||||
|
which served as a fantastic reference for deep IDE integration features.
|
||||||
|
|
||||||
|
- The members of the `Zig Programming Language` discord server's `#tooling-dev` channel for providing encouragement,
|
||||||
|
feedback, and lots of bug reports.
|
||||||
|
|
||||||
|
- The Ballerina Platform developers for `lsp4intellij`, the language server connector between the IntelliJ platform
|
||||||
|
and the Eclipse LSP4J project.
|
||||||
|
|
||||||
|
- The developers of the [intellij-rust](https://github.com/intellij-rust/intellij-rust/) plugin for providing an
|
||||||
|
excellent example on how to write debugger support that doesn't depend on CLion.
|
||||||
|
|
||||||
|
- All the people who have generously funded the project
|
||||||
|
- gree7
|
||||||
|
- xceno
|
||||||
|
- AnErrupTion
|
||||||
|
|
||||||
|
- Every contributor who helped with bugfixes and extra features
|
||||||
|
- [gatesn](https://github.com/gatesn)
|
||||||
|
- [MarioAriasC](https://github.com/MarioAriasC)
|
||||||
|
- [JensvandeWiel](https://github.com/JensvandeWiel)
|
||||||
|
|
||||||
|
- And everyone who actively reported issues and helped ironing out all the remaining problems
|
||||||
|
|
||||||
## Versioning scheme
|
## Versioning scheme
|
||||||
To reduce confusion and to better utilize semver, the plugin uses the following versioning scheme:
|
To reduce confusion and to better utilize semver, the plugin uses the following versioning scheme:
|
||||||
|
|
||||||
|
@ -34,45 +73,16 @@ Note: before version 11, the version scheme used was 0.X.Y, without separate pat
|
||||||
As this plugin will constantly be evolving together with the zig language, it makes no sense to keep the 0 prefix,
|
As this plugin will constantly be evolving together with the zig language, it makes no sense to keep the 0 prefix,
|
||||||
and might as well utilize the full semver string for extra information.
|
and might as well utilize the full semver string for extra information.
|
||||||
|
|
||||||
# Credits
|
|
||||||
|
|
||||||
## Supporters
|
|
||||||
|
|
||||||
- ### [Techatrix](https://github.com/Techatrix)
|
|
||||||
- ### [nuxusr](https://github.com/nuxusr)
|
|
||||||
- gree7
|
|
||||||
- xceno
|
|
||||||
- AnErrupTion
|
|
||||||
|
|
||||||
## Contributors
|
|
||||||
|
|
||||||
- [gatesn](https://github.com/gatesn)
|
|
||||||
- [MarioAriasC](https://github.com/MarioAriasC)
|
|
||||||
- [JensvandeWiel](https://github.com/JensvandeWiel)
|
|
||||||
|
|
||||||
## Additional Thanks
|
|
||||||
|
|
||||||
- The [ZigTools](https://github.com/zigtools/) team for developing the Zig Language Server.
|
|
||||||
|
|
||||||
- [HTGAzureX1212](https://github.com/HTGAzureX1212) for developing [intellij-zig](https://github.com/intellij-zig/intellij-zig),
|
|
||||||
which served as a fantastic reference for deep IDE integration features.
|
|
||||||
|
|
||||||
- The members of the `Zig Programming Language` discord server's `#tooling-dev` channel for providing encouragement,
|
|
||||||
feedback, and lots of bug reports.
|
|
||||||
|
|
||||||
- The developers of [LSP4IJ](https://github.com/redhat-developer/lsp4ij) for providing a really good LSP backend
|
|
||||||
|
|
||||||
- The developers of the [intellij-rust](https://github.com/intellij-rust/intellij-rust/) plugin for providing an
|
|
||||||
excellent example on how to write debugger support that doesn't depend on CLion.
|
|
||||||
|
|
||||||
- And everyone who actively reported issues and helped ironing out all the remaining problems
|
|
||||||
|
|
||||||
# Description
|
# Description
|
||||||
|
|
||||||
<!-- Plugin description -->
|
<!-- Plugin description -->
|
||||||
Adds support for the Zig Language, utilizing the ZLS language server for advanced coding assistance.
|
Adds support for the Zig Language, utilizing the ZLS language server for advanced coding assistance.
|
||||||
|
|
||||||
Before you can properly use the plugin, you need to select or download the Zig toolchain and language server in `Settings` -> `Languages & Frameworks` -> `Zig`.
|
## Quick setup guide for Zig and ZLS
|
||||||
|
|
||||||
|
1. Download the latest version of Zig from https://ziglang.org/download
|
||||||
|
2. Download and compile the ZLS language server, available at https://github.com/zigtools/zls
|
||||||
|
3. Go to `Settings` -> `Languages & Frameworks` -> `Zig`, and point the `Toolchain Location` and `ZLS path` to the correct places
|
||||||
|
|
||||||
## Debugging
|
## Debugging
|
||||||
|
|
||||||
|
@ -86,7 +96,6 @@ Debugging Zig code is supported in any native debugging capable IDE. The followi
|
||||||
- RustRover (including the non-commercial free version too)
|
- RustRover (including the non-commercial free version too)
|
||||||
- GoLand
|
- GoLand
|
||||||
- PyCharm Professional
|
- PyCharm Professional
|
||||||
- Android Studio
|
|
||||||
|
|
||||||
Additionally, in CLion, the plugin uses the C++ Toolchains for sourcing the debugger (this can be toggled off in the settings).
|
Additionally, in CLion, the plugin uses the C++ Toolchains for sourcing the debugger (this can be toggled off in the settings).
|
||||||
|
|
||||||
|
|
484
build.gradle.kts
484
build.gradle.kts
|
@ -1,122 +1,295 @@
|
||||||
|
import de.undercouch.gradle.tasks.download.Download
|
||||||
|
import groovy.xml.XmlParser
|
||||||
import org.jetbrains.changelog.Changelog
|
import org.jetbrains.changelog.Changelog
|
||||||
import org.jetbrains.changelog.markdownToHTML
|
import org.jetbrains.changelog.markdownToHTML
|
||||||
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
|
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
|
||||||
|
import org.jetbrains.intellij.platform.gradle.tasks.PatchPluginXmlTask
|
||||||
import org.jetbrains.intellij.platform.gradle.tasks.PublishPluginTask
|
import org.jetbrains.intellij.platform.gradle.tasks.PublishPluginTask
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
|
import org.jetbrains.intellij.platform.gradle.utils.extensionProvider
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
|
|
||||||
|
fun properties(key: String) = providers.gradleProperty(key)
|
||||||
|
fun environment(key: String) = providers.environmentVariable(key)
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "2.1.10" apply false
|
java
|
||||||
kotlin("plugin.serialization") version "2.1.10" apply false
|
|
||||||
id("org.jetbrains.intellij.platform") version "2.5.0"
|
|
||||||
id("org.jetbrains.changelog") version "2.2.1"
|
|
||||||
id("org.jetbrains.grammarkit") version "2022.3.2.2" apply false
|
|
||||||
idea
|
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
|
`java-library`
|
||||||
|
id("org.jetbrains.intellij.platform") version("2.0.0-beta8")
|
||||||
|
id("org.jetbrains.changelog") version("2.2.1")
|
||||||
|
id("org.jetbrains.grammarkit") version("2022.3.2.2")
|
||||||
|
id("de.undercouch.download") version("5.6.0")
|
||||||
}
|
}
|
||||||
val publishVersions = listOf("241", "242", "243", "251")
|
|
||||||
val pluginVersionFull get() = "$pluginVersion-$pluginSinceBuild"
|
val publishVersions = listOf("232", "233", "241", "242")
|
||||||
val pluginVersion: String by project
|
|
||||||
val pluginSinceBuild: String by project
|
val gitVersion: groovy.lang.Closure<String> by extra
|
||||||
val pluginUntilBuild: String by project
|
|
||||||
val javaVersion = property("javaVersion").toString().toInt()
|
val grammarKitGenDir = "build/generated/sources/grammarkit/java"
|
||||||
val lsp4ijVersion: String by project
|
val rootPackage = "com.falsepattern.zigbrains"
|
||||||
val runIdeTarget: String by project
|
|
||||||
val lsp4ijNightly = property("lsp4ijNightly").toString().toBoolean()
|
val rootPackagePath = rootPackage.replace('.', '/')
|
||||||
val useInstaller = property("useInstaller").toString().toBoolean()
|
|
||||||
|
// Keep these in sync with whatever the oldest IDE version we're targeting in gradle.properties needs
|
||||||
|
val javaLangVersion: JavaLanguageVersion = JavaLanguageVersion.of(21)
|
||||||
|
val javaVersion = JavaVersion.VERSION_21
|
||||||
|
|
||||||
|
val baseIDE = properties("baseIDE").get()
|
||||||
|
val ideaVersion = properties("ideaVersion").get()
|
||||||
|
val clionVersion = properties("clionVersion").get()
|
||||||
|
|
||||||
|
val clionPlugins = listOf("com.intellij.clion", "com.intellij.cidr.lang", "com.intellij.cidr.base", "com.intellij.nativeDebug")
|
||||||
|
|
||||||
|
val lsp4jVersion = "0.21.1"
|
||||||
|
val lsp4ijVersion = "0.3.0-20240718-013045"
|
||||||
|
|
||||||
|
val lsp4ijNightly = lsp4ijVersion.contains("-")
|
||||||
|
val lsp4ijDepString = "${if (lsp4ijNightly) "nightly." else ""}com.jetbrains.plugins:com.redhat.devtools.lsp4ij:$lsp4ijVersion"
|
||||||
val lsp4ijPluginString = "com.redhat.devtools.lsp4ij:$lsp4ijVersion${if (lsp4ijNightly) "@nightly" else ""}"
|
val lsp4ijPluginString = "com.redhat.devtools.lsp4ij:$lsp4ijVersion${if (lsp4ijNightly) "@nightly" else ""}"
|
||||||
val ideaCommunityVersion: String by project
|
|
||||||
val clionVersion: String by project
|
|
||||||
|
|
||||||
group = "com.falsepattern"
|
val lsp4ijDep: DependencyHandler.() -> Unit = {
|
||||||
version = pluginVersionFull
|
intellijPlatformPluginDependency(lsp4ijDepString)
|
||||||
|
compileOnlyApi(lsp4ijDepString)
|
||||||
subprojects {
|
compileOnlyApi("org.eclipse.lsp4j:org.eclipse.lsp4j:$lsp4jVersion")
|
||||||
apply(plugin = "java")
|
|
||||||
apply(plugin = "org.jetbrains.kotlin.jvm")
|
|
||||||
apply(plugin = "org.jetbrains.intellij.platform.module")
|
|
||||||
apply(plugin = "idea")
|
|
||||||
|
|
||||||
extensions.configure<KotlinJvmProjectExtension>("kotlin") {
|
|
||||||
jvmToolchain(javaVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType<KotlinCompilationTask<*>>().configureEach {
|
|
||||||
compilerOptions {
|
|
||||||
freeCompilerArgs.addAll("-Xlambdas=indy")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
processResources {
|
wrapper {
|
||||||
from("LICENSE")
|
gradleVersion = properties("gradleVersion").get()
|
||||||
from("licenses") {
|
|
||||||
into("licenses")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun pluginVersion(): Provider<String> {
|
||||||
|
return provider {
|
||||||
|
System.getenv("RELEASE_VERSION")
|
||||||
|
}.orElse(properties("pluginVersion"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pluginVersionFull(): Provider<String> {
|
||||||
|
return pluginVersion().map { it + "-" + properties("pluginSinceBuild").get() }
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
idea {
|
apply {
|
||||||
module {
|
plugin("org.jetbrains.intellij.platform")
|
||||||
isDownloadSources = true
|
}
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
intellijPlatform {
|
||||||
|
localPlatformArtifacts {
|
||||||
|
content {
|
||||||
|
includeGroup("bundledPlugin")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
marketplace {
|
||||||
|
content {
|
||||||
|
includeGroup("com.jetbrains.plugins")
|
||||||
|
includeGroup("nightly.com.jetbrains.plugins")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snapshots {
|
||||||
|
content {
|
||||||
|
includeModule("com.jetbrains.intellij.clion", "clion")
|
||||||
|
includeModule("com.jetbrains.intellij.idea", "ideaIC")
|
||||||
|
includeModule("com.jetbrains.intellij.idea", "ideaIU")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
compileOnly("org.projectlombok:lombok:1.18.32")
|
||||||
|
annotationProcessor("org.projectlombok:lombok:1.18.32")
|
||||||
|
if (path !in listOf(":", ":plugin", ":debugger")) {
|
||||||
|
intellijPlatform {
|
||||||
|
intellijIdeaCommunity(ideaVersion)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (path in listOf(":zig", ":zon")) {
|
||||||
|
apply {
|
||||||
|
plugin("org.jetbrains.grammarkit")
|
||||||
|
}
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
java {
|
java {
|
||||||
|
srcDirs(
|
||||||
|
"${grammarKitGenDir}/lexer",
|
||||||
|
"${grammarKitGenDir}/parser"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tasks {
|
||||||
|
|
||||||
|
generateLexer {
|
||||||
|
enabled = true
|
||||||
|
purgeOldFiles = true
|
||||||
|
}
|
||||||
|
|
||||||
|
generateParser {
|
||||||
|
enabled = true
|
||||||
|
targetRootOutputDir = file("${grammarKitGenDir}/parser")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
register<DefaultTask>("generateGrammars") {
|
||||||
|
description = "Generate source code from parser/lexer definitions"
|
||||||
|
group = "build setup"
|
||||||
|
dependsOn("generateLexer")
|
||||||
|
dependsOn("generateParser")
|
||||||
|
}
|
||||||
|
|
||||||
|
compileJava {
|
||||||
|
dependsOn("generateGrammars")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configure<JavaPluginExtension> {
|
||||||
toolchain {
|
toolchain {
|
||||||
languageVersion = JavaLanguageVersion.of(javaVersion)
|
languageVersion.set(javaLangVersion)
|
||||||
@Suppress("UnstableApiUsage")
|
|
||||||
vendor = JvmVendorSpec.JETBRAINS
|
vendor = JvmVendorSpec.JETBRAINS
|
||||||
}
|
}
|
||||||
sourceCompatibility = JavaVersion.toVersion(javaVersion)
|
sourceCompatibility = javaVersion
|
||||||
targetCompatibility = JavaVersion.toVersion(javaVersion)
|
targetCompatibility = javaVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
tasks.withType(JavaCompile::class) {
|
||||||
exclusiveContent {
|
options.encoding = "UTF-8"
|
||||||
forRepository {
|
|
||||||
maven {
|
|
||||||
setUrl("https://mvn.falsepattern.com/releases")
|
|
||||||
name = "mavenpattern"
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
filter {
|
|
||||||
includeModule("com.redhat.devtools.intellij", "lsp4ij")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mavenCentral()
|
|
||||||
|
|
||||||
|
|
||||||
|
group = properties("pluginGroup").get()
|
||||||
|
version = pluginVersionFull().get()
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
runIde { enabled = false }
|
||||||
|
prepareSandbox { enabled = false }
|
||||||
|
buildSearchableOptions { enabled = false }
|
||||||
|
verifyPlugin { enabled = false }
|
||||||
|
buildPlugin { enabled = false }
|
||||||
|
signPlugin { enabled = false }
|
||||||
|
verifyPluginProjectConfiguration { enabled = false }
|
||||||
|
|
||||||
|
withType<PatchPluginXmlTask> {
|
||||||
|
sinceBuild = properties("pluginSinceBuild")
|
||||||
|
untilBuild = properties("pluginUntilBuild")
|
||||||
|
}
|
||||||
|
}
|
||||||
intellijPlatform {
|
intellijPlatform {
|
||||||
defaultRepositories()
|
instrumentCode = false
|
||||||
snapshots()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
project(":common") {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
project(":zig") {
|
||||||
|
apply {
|
||||||
|
plugin("java-library")
|
||||||
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation(project(":common"))
|
||||||
|
lsp4ijDep()
|
||||||
intellijPlatform {
|
intellijPlatform {
|
||||||
when(runIdeTarget) {
|
|
||||||
"ideaCommunity" -> create(IntelliJPlatformType.IntellijIdeaCommunity, ideaCommunityVersion, useInstaller = useInstaller)
|
|
||||||
"clion" -> create(IntelliJPlatformType.CLion, clionVersion, useInstaller = useInstaller)
|
|
||||||
}
|
|
||||||
|
|
||||||
pluginVerifier()
|
|
||||||
zipSigner()
|
|
||||||
plugin(lsp4ijPluginString)
|
plugin(lsp4ijPluginString)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
tasks {
|
||||||
|
generateLexer {
|
||||||
|
sourceFile = file("src/main/grammar/Zig.flex")
|
||||||
|
targetOutputDir = file("${grammarKitGenDir}/lexer/${rootPackagePath}/zig/lexer")
|
||||||
|
}
|
||||||
|
|
||||||
runtimeOnly(project(":core"))
|
generateParser {
|
||||||
runtimeOnly(project(":cidr"))
|
sourceFile = file("src/main/grammar/Zig.bnf")
|
||||||
runtimeOnly(project(":lsp"))
|
pathToParser = "${rootPackagePath}/zig/psi/ZigParser.java"
|
||||||
|
pathToPsiRoot = "${rootPackagePath}/zig/psi"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project(":project") {
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":common"))
|
||||||
|
implementation(project(":zig"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project(":debugger") {
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":zig"))
|
||||||
|
implementation(project(":project"))
|
||||||
|
implementation(project(":common"))
|
||||||
|
implementation("org.eclipse.lsp4j:org.eclipse.lsp4j.debug:$lsp4jVersion") {
|
||||||
|
exclude("org.eclipse.lsp4j", "org.eclipse.lsp4j")
|
||||||
|
exclude("org.eclipse.lsp4j", "org.eclipse.lsp4j.jsonrpc")
|
||||||
|
exclude("com.google.code.gson", "gson")
|
||||||
|
}
|
||||||
|
intellijPlatform {
|
||||||
|
clion(clionVersion)
|
||||||
|
for (p in clionPlugins) {
|
||||||
|
bundledPlugin(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val genOutputDir = layout.buildDirectory.dir("generated-resources")
|
||||||
|
sourceSets["main"].resources.srcDir(genOutputDir)
|
||||||
|
tasks {
|
||||||
|
register<Download>("downloadProps") {
|
||||||
|
src("https://falsepattern.com/zigbrains/msvc.properties")
|
||||||
|
dest(genOutputDir.map { it.file("msvc.properties") })
|
||||||
|
}
|
||||||
|
|
||||||
|
processResources {
|
||||||
|
dependsOn("downloadProps")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project(":zon") {
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":common"))
|
||||||
|
}
|
||||||
|
tasks {
|
||||||
|
generateLexer {
|
||||||
|
sourceFile = file("src/main/grammar/Zon.flex")
|
||||||
|
targetOutputDir = file("${grammarKitGenDir}/lexer/${rootPackagePath}/zon/lexer")
|
||||||
|
}
|
||||||
|
|
||||||
|
generateParser {
|
||||||
|
sourceFile = file("src/main/grammar/Zon.bnf")
|
||||||
|
pathToParser = "${rootPackagePath}/zon/psi/ZonParser.java"
|
||||||
|
pathToPsiRoot = "${rootPackagePath}/zon/psi"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project(":plugin") {
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":common"))
|
||||||
|
implementation(project(":zig"))
|
||||||
|
implementation(project(":project"))
|
||||||
|
implementation(project(":zon"))
|
||||||
|
implementation(project(":debugger"))
|
||||||
|
intellijPlatform {
|
||||||
|
zipSigner()
|
||||||
|
pluginVerifier()
|
||||||
|
when (baseIDE) {
|
||||||
|
"idea" -> intellijIdeaCommunity(ideaVersion)
|
||||||
|
"clion" -> clion(clionVersion)
|
||||||
|
}
|
||||||
|
plugin(lsp4ijPluginString)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
intellijPlatform {
|
intellijPlatform {
|
||||||
|
projectName = "ZigBrains"
|
||||||
pluginConfiguration {
|
pluginConfiguration {
|
||||||
version = pluginVersionFull
|
name = properties("pluginName")
|
||||||
|
description = providers.fileContents(rootProject.layout.projectDirectory.file("README.md")).asText.map {
|
||||||
description = providers.fileContents(layout.projectDirectory.file("README.md")).asText.map {
|
|
||||||
val start = "<!-- Plugin description -->"
|
val start = "<!-- Plugin description -->"
|
||||||
val end = "<!-- Plugin description end -->"
|
val end = "<!-- Plugin description end -->"
|
||||||
|
|
||||||
|
@ -127,85 +300,128 @@ intellijPlatform {
|
||||||
subList(indexOf(start) + 1, indexOf(end)).joinToString("\n").let(::markdownToHTML)
|
subList(indexOf(start) + 1, indexOf(end)).joinToString("\n").let(::markdownToHTML)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
changeNotes = pluginVersion().map { pluginVersion ->
|
||||||
val changelog = project.changelog
|
with(rootProject.changelog) {
|
||||||
|
|
||||||
changeNotes = provider { pluginVersion }.map { pluginVersion ->
|
|
||||||
with(changelog) {
|
|
||||||
renderItem(
|
renderItem(
|
||||||
(getOrNull(pluginVersion) ?: getUnreleased())
|
(getOrNull(pluginVersion) ?: getUnreleased())
|
||||||
.withHeader(false)
|
.withHeader(false)
|
||||||
.withEmptySections(false),
|
.withEmptySections(false),
|
||||||
Changelog.OutputType.HTML
|
Changelog.OutputType.HTML,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
version = pluginVersionFull()
|
||||||
ideaVersion {
|
|
||||||
sinceBuild = pluginSinceBuild
|
|
||||||
if (pluginUntilBuild.isNotBlank()) {
|
|
||||||
untilBuild = pluginUntilBuild
|
|
||||||
} else {
|
|
||||||
untilBuild = provider { null }
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
signing {
|
signing {
|
||||||
certificateChainFile = file("secrets/chain.crt")
|
certificateChainFile = rootProject.file("secrets/chain.crt")
|
||||||
privateKeyFile = file("secrets/private.pem")
|
privateKeyFile = rootProject.file("secrets/private.pem")
|
||||||
password = providers.environmentVariable("PRIVATE_KEY_PASSWORD")
|
password = environment("PRIVATE_KEY_PASSWORD")
|
||||||
}
|
}
|
||||||
|
verifyPlugin {
|
||||||
pluginVerification {
|
|
||||||
ides {
|
ides {
|
||||||
select {
|
ide(IntelliJPlatformType.IntellijIdeaCommunity, ideaVersion)
|
||||||
types = listOf(
|
ide(IntelliJPlatformType.IntellijIdeaUltimate, ideaVersion)
|
||||||
IntelliJPlatformType.IntellijIdeaCommunity,
|
ide(IntelliJPlatformType.CLion, clionVersion)
|
||||||
IntelliJPlatformType.IntellijIdeaUltimate,
|
|
||||||
IntelliJPlatformType.CLion
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buildSearchableOptions = false
|
|
||||||
instrumentCode = false
|
|
||||||
}
|
|
||||||
|
|
||||||
changelog {
|
// Include the generated files in the source set
|
||||||
groups.empty()
|
|
||||||
repositoryUrl = providers.gradleProperty("pluginRepositoryUrl")
|
// Collects all jars produced by compilation of project modules and merges them into singe one.
|
||||||
|
// We need to put all plugin manifest files into single jar to make new plugin model work
|
||||||
|
val mergePluginJarTask = task<Jar>("mergePluginJars") {
|
||||||
|
duplicatesStrategy = DuplicatesStrategy.FAIL
|
||||||
|
archiveBaseName.set("ZigBrains")
|
||||||
|
|
||||||
|
exclude("META-INF/MANIFEST.MF")
|
||||||
|
exclude("**/classpath.index")
|
||||||
|
|
||||||
|
val pluginLibDir by lazy {
|
||||||
|
val sandboxTask = tasks.prepareSandbox.get()
|
||||||
|
sandboxTask.destinationDir.resolve("${project.extensionProvider.map { it.projectName }.get()}/lib")
|
||||||
|
}
|
||||||
|
|
||||||
|
val pluginJars by lazy {
|
||||||
|
pluginLibDir.listFiles().orEmpty().filter { it.isPluginJar() }
|
||||||
|
}
|
||||||
|
|
||||||
|
destinationDirectory.set(project.layout.dir(provider { pluginLibDir }))
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
for (file in pluginJars) {
|
||||||
|
from(zipTree(file))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
delete(pluginJars)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
publishPlugin {
|
runIde {
|
||||||
dependsOn(patchChangelog)
|
dependsOn(mergePluginJarTask)
|
||||||
|
enabled = true
|
||||||
}
|
}
|
||||||
compileJava {
|
|
||||||
enabled = false
|
prepareSandbox {
|
||||||
|
finalizedBy(mergePluginJarTask)
|
||||||
|
enabled = true
|
||||||
}
|
}
|
||||||
classes {
|
|
||||||
enabled = false
|
buildSearchableOptions {
|
||||||
|
dependsOn(mergePluginJarTask)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
verifyPlugin {
|
||||||
|
dependsOn(mergePluginJarTask)
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyPluginProjectConfiguration {
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
signPlugin {
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
verifyPluginSignature {
|
verifyPluginSignature {
|
||||||
certificateChainFile = file("secrets/chain.crt")
|
|
||||||
inputArchiveFile = signPlugin.map { it.signedArchiveFile }.get()
|
|
||||||
dependsOn(signPlugin)
|
dependsOn(signPlugin)
|
||||||
}
|
}
|
||||||
publishPlugin {
|
|
||||||
|
buildPlugin {
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
intellijPlatform {
|
||||||
|
when (baseIDE) {
|
||||||
|
"idea" -> intellijIdeaCommunity(ideaVersion)
|
||||||
|
"clion" -> clion(clionVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
generateLexer {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
generateParser {
|
||||||
enabled = false
|
enabled = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun distFile(it: String) = layout.buildDirectory.file("dist/ZigBrains-${pluginVersion().get()}-$it-signed.zip")
|
||||||
fun distFile(it: String) = layout.buildDirectory.file("dist/ZigBrains-$pluginVersion-$it-signed.zip")
|
|
||||||
|
|
||||||
publishVersions.forEach {
|
publishVersions.forEach {
|
||||||
tasks.register<PublishPluginTask>("jbpublish-$it").configure {
|
tasks.register<PublishPluginTask>("jbpublish-$it").configure {
|
||||||
archiveFile = distFile(it)
|
archiveFile = distFile(it)
|
||||||
token = providers.environmentVariable("IJ_PUBLISH_TOKEN")
|
token = environment("IJ_PUBLISH_TOKEN")
|
||||||
channels = if (pluginVersion.contains("-")) listOf("nightly") else listOf("default")
|
channels = if (pluginVersion().get().contains("-")) listOf("nightly") else listOf("default")
|
||||||
setDependsOn(dependsOn.filter { if (it is TaskProvider<*>) it.name != "signPlugin" && it.name != "buildPlugin" else true })
|
|
||||||
}
|
}
|
||||||
tasks.named("publish").configure {
|
tasks.named("publish").configure {
|
||||||
dependsOn("jbpublish-$it")
|
dependsOn("jbpublish-$it")
|
||||||
|
@ -217,7 +433,7 @@ publishing {
|
||||||
create<MavenPublication>("maven") {
|
create<MavenPublication>("maven") {
|
||||||
groupId = "com.falsepattern"
|
groupId = "com.falsepattern"
|
||||||
artifactId = "zigbrains"
|
artifactId = "zigbrains"
|
||||||
version = pluginVersion
|
version = pluginVersion().get()
|
||||||
|
|
||||||
publishVersions.forEach {
|
publishVersions.forEach {
|
||||||
artifact(distFile(it)) {
|
artifact(distFile(it)) {
|
||||||
|
@ -238,3 +454,21 @@ publishing {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun File.isPluginJar(): Boolean {
|
||||||
|
if (!isFile) return false
|
||||||
|
if (extension != "jar") return false
|
||||||
|
return zipTree(this).files.any { it.isManifestFile() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun File.isManifestFile(): Boolean {
|
||||||
|
if (extension != "xml") return false
|
||||||
|
val rootNode = try {
|
||||||
|
val parser = XmlParser()
|
||||||
|
parser.parse(this)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.error("Failed to parse $path", e)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return rootNode.name() == "idea-plugin"
|
||||||
|
}
|
||||||
|
|
32
build.sh
32
build.sh
|
@ -1,29 +1,23 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
# This file is part of ZigBrains.
|
# Copyright 2023-2024 FalsePattern
|
||||||
#
|
#
|
||||||
# Copyright (C) 2023-2025 FalsePattern
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# All Rights Reserved
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
#
|
#
|
||||||
# The above copyright notice and this permission notice shall be included
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
# in all copies or substantial portions of the Software.
|
|
||||||
#
|
#
|
||||||
# ZigBrains is free software: you can redistribute it and/or modify
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# it under the terms of the GNU Lesser General Public License as published by
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# the Free Software Foundation, only version 3 of the License.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
#
|
# See the License for the specific language governing permissions and
|
||||||
# ZigBrains is distributed in the hope that it will be useful,
|
# limitations under the License.
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Lesser General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
|
||||||
# along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
#
|
#
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
declare -a branches=("master" "243" "242" "241")
|
declare -a branches=("master" "241" "233" "232")
|
||||||
|
|
||||||
DEFAULT_BRANCH="${branches[0]}"
|
DEFAULT_BRANCH="${branches[0]}"
|
||||||
|
|
||||||
|
@ -70,7 +64,7 @@ fi
|
||||||
for i in "${branches[@]}"
|
for i in "${branches[@]}"
|
||||||
do
|
do
|
||||||
echo "Building branch $i"
|
echo "Building branch $i"
|
||||||
git checkout "$i" && ./gradlew verifyPluginSignature
|
git checkout "$i" && ./gradlew :plugin:verifyPluginSignature
|
||||||
RESULT=$?
|
RESULT=$?
|
||||||
if [ $RESULT != 0 ]; then
|
if [ $RESULT != 0 ]; then
|
||||||
echo "Failed to build plugin on branch $i!"
|
echo "Failed to build plugin on branch $i!"
|
||||||
|
@ -82,6 +76,6 @@ git checkout "$DEFAULT_BRANCH"
|
||||||
|
|
||||||
mkdir -p build/dist
|
mkdir -p build/dist
|
||||||
|
|
||||||
cp build/distributions/*-signed.zip build/dist/
|
cp modules/plugin/build/distributions/*-signed.zip build/dist/
|
||||||
|
|
||||||
./gradlew publish
|
./gradlew publish
|
|
@ -1,46 +0,0 @@
|
||||||
import de.undercouch.gradle.tasks.download.Download
|
|
||||||
import org.jetbrains.intellij.platform.gradle.Constants
|
|
||||||
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
id("de.undercouch.download") version("5.6.0")
|
|
||||||
}
|
|
||||||
val lsp4jVersion: String by project
|
|
||||||
val clionVersion: String by project
|
|
||||||
val useInstaller = property("useInstaller").toString().toBoolean()
|
|
||||||
|
|
||||||
val genOutputDir = layout.buildDirectory.dir("generated-resources")
|
|
||||||
sourceSets["main"].resources.srcDir(genOutputDir)
|
|
||||||
|
|
||||||
tasks {
|
|
||||||
register<Download>("downloadProps") {
|
|
||||||
onlyIfModified(true)
|
|
||||||
useETag(true)
|
|
||||||
src("https://falsepattern.com/zigbrains/msvc.properties")
|
|
||||||
dest(genOutputDir.map { it.file("msvc.properties") })
|
|
||||||
}
|
|
||||||
processResources {
|
|
||||||
dependsOn("downloadProps")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
intellijPlatform {
|
|
||||||
create(IntelliJPlatformType.CLion, clionVersion, useInstaller = useInstaller)
|
|
||||||
bundledPlugins("com.intellij.clion", "com.intellij.cidr.base", "com.intellij.nativeDebug")
|
|
||||||
}
|
|
||||||
implementation(project(":core")) {
|
|
||||||
isTransitive = false
|
|
||||||
}
|
|
||||||
implementation("org.eclipse.lsp4j:org.eclipse.lsp4j.debug:$lsp4jVersion") {
|
|
||||||
exclude("org.eclipse.lsp4j", "org.eclipse.lsp4j")
|
|
||||||
exclude("org.eclipse.lsp4j", "org.eclipse.lsp4j.jsonrpc")
|
|
||||||
exclude("com.google.code.gson", "gson")
|
|
||||||
}
|
|
||||||
compileOnly("org.eclipse.lsp4j:org.eclipse.lsp4j:$lsp4jVersion")
|
|
||||||
}
|
|
||||||
configurations[Constants.Configurations.INTELLIJ_PLATFORM_BUNDLED_PLUGINS].dependencies.configureEach {
|
|
||||||
if (this is ExternalModuleDependency) {
|
|
||||||
this.isTransitive = false
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.cidr
|
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.jetbrains.cidr.project.workspace.CidrWorkspace
|
|
||||||
import com.jetbrains.cidr.project.workspace.OCRootsSynchronizer
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class ZigWorkspace(project: Project) : CidrWorkspace(project) {
|
|
||||||
override fun collectRootsInfo(p0: File?): OCRootsSynchronizer.RootsInfo {
|
|
||||||
return OCRootsSynchronizer.RootsInfo()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getClientKey(): String {
|
|
||||||
return "ZIG_WORKSPACE"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.cidr
|
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.project.guessProjectDir
|
|
||||||
import com.intellij.openapi.vfs.toNioPathOrNull
|
|
||||||
import com.jetbrains.cidr.project.workspace.CidrWorkspace
|
|
||||||
import com.jetbrains.cidr.project.workspace.CidrWorkspaceManager
|
|
||||||
import com.jetbrains.cidr.project.workspace.CidrWorkspaceProvider
|
|
||||||
import java.io.IOException
|
|
||||||
import java.nio.file.Files
|
|
||||||
import kotlin.io.path.pathString
|
|
||||||
|
|
||||||
class ZigWorkspaceProvider: CidrWorkspaceProvider {
|
|
||||||
override fun getWorkspace(project: Project): CidrWorkspace? {
|
|
||||||
getExistingWorkspace(project)?.let { return it }
|
|
||||||
|
|
||||||
val projectDir = project.guessProjectDir()?.toNioPathOrNull() ?: return null
|
|
||||||
try {
|
|
||||||
Files.walk(projectDir).use { files ->
|
|
||||||
if (files.anyMatch { it.fileName.pathString.let { it2 -> it2.endsWith(".zig") || it2.endsWith(".zig.zon") } }) {
|
|
||||||
return ZigWorkspace(project)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: IOException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun loadWorkspace(project: Project) {
|
|
||||||
if (getExistingWorkspace(project) != null)
|
|
||||||
return
|
|
||||||
val workspace = getWorkspace(project)
|
|
||||||
if (workspace != null) {
|
|
||||||
val manager = CidrWorkspaceManager.getInstance(project)
|
|
||||||
manager.markInitializing(workspace)
|
|
||||||
manager.markInitialized(workspace)
|
|
||||||
manager.markLoading(workspace)
|
|
||||||
manager.markLoaded(workspace)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getExistingWorkspace(project: Project): ZigWorkspace? {
|
|
||||||
val workspaces = CidrWorkspaceManager.getInstance(project).workspaces.keys
|
|
||||||
for (ws in workspaces)
|
|
||||||
if (ws is ZigWorkspace)
|
|
||||||
return ws
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.clion
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.ZigDebuggerDriverConfigurationProvider
|
|
||||||
import com.falsepattern.zigbrains.debugger.settings.ZigDebuggerSettings
|
|
||||||
import com.intellij.openapi.diagnostic.logger
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.util.SystemInfo
|
|
||||||
import com.jetbrains.cidr.cpp.execution.debugger.backend.CLionGDBDriverConfiguration
|
|
||||||
import com.jetbrains.cidr.cpp.execution.debugger.backend.CLionLLDBDriverConfiguration
|
|
||||||
import com.jetbrains.cidr.cpp.toolchains.CPPDebugger
|
|
||||||
import com.jetbrains.cidr.cpp.toolchains.CPPToolchains
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
|
|
||||||
|
|
||||||
class ZigClionDebuggerDriverConfigurationProvider: ZigDebuggerDriverConfigurationProvider() {
|
|
||||||
override suspend fun getDebuggerConfiguration(
|
|
||||||
project: Project,
|
|
||||||
isElevated: Boolean,
|
|
||||||
emulateTerminal: Boolean
|
|
||||||
): DebuggerDriverConfiguration? {
|
|
||||||
if (SystemInfo.isWindows)
|
|
||||||
return null
|
|
||||||
|
|
||||||
if (!ZigDebuggerSettings.instance.useClion)
|
|
||||||
return null
|
|
||||||
|
|
||||||
val toolchains = CPPToolchains.getInstance()
|
|
||||||
var toolchain = toolchains.getToolchainByNameOrDefault("Zig")
|
|
||||||
if (toolchain == null || !toolchain.isDebuggerSupported) {
|
|
||||||
LOG.info("Couldn't find debug-compatible C++ toolchain with name \"Zig\"")
|
|
||||||
toolchain = toolchains.defaultToolchain
|
|
||||||
}
|
|
||||||
if (toolchain == null || !toolchain.isDebuggerSupported) {
|
|
||||||
LOG.info("Couldn't find debug-compatible C++ default toolchain")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
return when(toolchain.debuggerKind) {
|
|
||||||
CPPDebugger.Kind.BUNDLED_GDB,
|
|
||||||
CPPDebugger.Kind.CUSTOM_GDB -> CLionGDBDriverConfiguration(project, toolchain, isEmulateTerminal = emulateTerminal)
|
|
||||||
CPPDebugger.Kind.BUNDLED_LLDB,
|
|
||||||
CPPDebugger.Kind.CUSTOM_LLDB -> CLionLLDBDriverConfiguration(project, toolchain, isEmulateTerminal = emulateTerminal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val LOG = logger<ZigClionDebuggerDriverConfigurationProvider>()
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugbridge
|
|
||||||
|
|
||||||
import com.intellij.openapi.extensions.ExtensionPointName
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
|
|
||||||
interface ZigDebuggerDriverConfigurationProviderBase {
|
|
||||||
companion object {
|
|
||||||
val EXTENSION_POINT_NAME = ExtensionPointName.create<ZigDebuggerDriverConfigurationProviderBase>("com.falsepattern.zigbrains.debuggerDriverProvider")
|
|
||||||
}
|
|
||||||
suspend fun <T> getDebuggerConfiguration(project: Project, isElevated: Boolean, emulateTerminal: Boolean, klass: Class<T>): T?
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.shared.ZBFeatures
|
|
||||||
|
|
||||||
class DebuggerFeatures: ZBFeatures {
|
|
||||||
override fun getDebug(): Boolean {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger
|
|
||||||
|
|
||||||
import com.intellij.DynamicBundle
|
|
||||||
import org.jetbrains.annotations.Nls
|
|
||||||
import org.jetbrains.annotations.NonNls
|
|
||||||
import org.jetbrains.annotations.PropertyKey
|
|
||||||
import java.util.function.Supplier
|
|
||||||
|
|
||||||
|
|
||||||
internal object ZigDebugBundle {
|
|
||||||
@NonNls
|
|
||||||
const val BUNDLE = "zigbrains.debugger.Bundle"
|
|
||||||
|
|
||||||
private val INSTANCE = DynamicBundle(ZigDebugBundle::class.java, BUNDLE)
|
|
||||||
|
|
||||||
fun message(
|
|
||||||
key: @PropertyKey(resourceBundle = BUNDLE) String,
|
|
||||||
vararg params: Any
|
|
||||||
): @Nls String {
|
|
||||||
return INSTANCE.getMessage(key, *params)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun lazyMessage(
|
|
||||||
key: @PropertyKey(resourceBundle = BUNDLE) String,
|
|
||||||
vararg params: Any
|
|
||||||
): Supplier<@Nls String> {
|
|
||||||
return INSTANCE.getLazyMessage(key, *params)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugbridge.ZigDebuggerDriverConfigurationProviderBase
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
|
|
||||||
|
|
||||||
abstract class ZigDebuggerDriverConfigurationProvider: ZigDebuggerDriverConfigurationProviderBase {
|
|
||||||
final override suspend fun <T> getDebuggerConfiguration(
|
|
||||||
project: Project,
|
|
||||||
isElevated: Boolean,
|
|
||||||
emulateTerminal: Boolean,
|
|
||||||
klass: Class<T>
|
|
||||||
): T? {
|
|
||||||
if (klass != DebuggerDriverConfiguration::class.java)
|
|
||||||
return null
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
return getDebuggerConfiguration(project, isElevated, emulateTerminal) as T
|
|
||||||
}
|
|
||||||
protected abstract suspend fun getDebuggerConfiguration(project: Project, isElevated: Boolean, emulateTerminal: Boolean): DebuggerDriverConfiguration?
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger
|
|
||||||
|
|
||||||
import com.jetbrains.cidr.execution.debugger.CidrDebuggerEditorsExtensionBase
|
|
||||||
|
|
||||||
class ZigDebuggerEditorsExtension: CidrDebuggerEditorsExtensionBase() {
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger
|
|
||||||
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriver.DebuggerLanguage
|
|
||||||
|
|
||||||
object ZigDebuggerLanguage: DebuggerLanguage {
|
|
||||||
override fun toString(): String {
|
|
||||||
return "Zig"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigExecConfig
|
|
||||||
import com.intellij.execution.configurations.RunProfile
|
|
||||||
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider
|
|
||||||
import com.jetbrains.cidr.execution.debugger.CidrDebuggerLanguageSupport
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriver
|
|
||||||
|
|
||||||
class ZigDebuggerLanguageSupport: CidrDebuggerLanguageSupport() {
|
|
||||||
override fun getSupportedDebuggerLanguages(): Set<DebuggerDriver.DebuggerLanguage> {
|
|
||||||
return setOf(ZigDebuggerLanguage)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createEditor(profile: RunProfile?): XDebuggerEditorsProvider? {
|
|
||||||
if (profile !is ZigExecConfig<*>)
|
|
||||||
return null
|
|
||||||
return createEditorProvider()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,157 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.settings.ZigDebuggerSettings
|
|
||||||
import com.falsepattern.zigbrains.debugger.toolchain.*
|
|
||||||
import com.falsepattern.zigbrains.debugger.win.MSVCDriverConfiguration
|
|
||||||
import com.falsepattern.zigbrains.shared.coroutine.withEDTContext
|
|
||||||
import com.falsepattern.zigbrains.zig.ZigLanguage
|
|
||||||
import com.intellij.openapi.application.ModalityState
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.ui.DoNotAskOption
|
|
||||||
import com.intellij.openapi.ui.MessageDialogBuilder
|
|
||||||
import com.intellij.openapi.ui.Messages
|
|
||||||
import com.jetbrains.cidr.ArchitectureType
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.gdb.GDBDriverConfiguration
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.lldb.LLDBDriverConfiguration
|
|
||||||
import java.io.File
|
|
||||||
import kotlin.io.path.pathString
|
|
||||||
|
|
||||||
class ZigDefaultDebuggerDriverConfigurationProvider: ZigDebuggerDriverConfigurationProvider() {
|
|
||||||
override suspend fun getDebuggerConfiguration(project: Project, isElevated: Boolean, emulateTerminal: Boolean): DebuggerDriverConfiguration? {
|
|
||||||
val settings = ZigDebuggerSettings.instance
|
|
||||||
val service = zigDebuggerToolchainService
|
|
||||||
val kind = settings.debuggerKind
|
|
||||||
if (!availabilityCheck(project, kind))
|
|
||||||
return null
|
|
||||||
|
|
||||||
return when(val availability = service.debuggerAvailability(kind)) {
|
|
||||||
DebuggerAvailability.Bundled -> when(kind) {
|
|
||||||
DebuggerKind.LLDB -> ZigLLDBDriverConfiguration(isElevated, emulateTerminal)
|
|
||||||
DebuggerKind.GDB -> ZigGDBDriverConfiguration(isElevated, emulateTerminal)
|
|
||||||
DebuggerKind.MSVC -> throw AssertionError("MSVC is never bundled")
|
|
||||||
}
|
|
||||||
is DebuggerAvailability.Binaries -> when(val binary = availability.binaries) {
|
|
||||||
is LLDBBinaries -> ZigCustomBinariesLLDBDriverConfiguration(binary, isElevated, emulateTerminal)
|
|
||||||
is GDBBinaries -> ZigCustomBinariesGDBDriverConfiguration(binary, isElevated, emulateTerminal)
|
|
||||||
is MSVCBinaries -> ZigMSVCDriverConfiguration(binary, isElevated, emulateTerminal)
|
|
||||||
else -> throw AssertionError("Unreachable")
|
|
||||||
}
|
|
||||||
DebuggerAvailability.Unavailable,
|
|
||||||
DebuggerAvailability.NeedToDownload,
|
|
||||||
DebuggerAvailability.NeedToUpdate -> throw AssertionError("Unreachable")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun availabilityCheck(project: Project, kind: DebuggerKind): Boolean {
|
|
||||||
val service = zigDebuggerToolchainService
|
|
||||||
val availability = service.debuggerAvailability(kind)
|
|
||||||
val (message, action) = when(availability) {
|
|
||||||
DebuggerAvailability.Unavailable -> return false
|
|
||||||
DebuggerAvailability.NeedToDownload ->
|
|
||||||
ZigDebugBundle.message("debugger.run.unavailable.reason.download") to ZigDebugBundle.message("debugger.run.unavailable.reason.download.button")
|
|
||||||
DebuggerAvailability.NeedToUpdate ->
|
|
||||||
ZigDebugBundle.message("debugger.run.unavailable.reason.update") to ZigDebugBundle.message("debugger.run.unavailable.reason.update.button")
|
|
||||||
DebuggerAvailability.Bundled,
|
|
||||||
is DebuggerAvailability.Binaries -> return true
|
|
||||||
}
|
|
||||||
|
|
||||||
val downloadDebugger = if (!ZigDebuggerSettings.instance.downloadAutomatically) {
|
|
||||||
showDialog(project, message, action)
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (downloadDebugger) {
|
|
||||||
val result = withEDTContext(ModalityState.any()) {
|
|
||||||
service.downloadDebugger(project, kind)
|
|
||||||
}
|
|
||||||
if (result is ZigDebuggerToolchainService.DownloadResult.Ok) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun showDialog(project: Project, message: String, action: String): Boolean {
|
|
||||||
val doNotAsk = object: DoNotAskOption.Adapter() {
|
|
||||||
override fun rememberChoice(isSelected: Boolean, exitCode: Int) {
|
|
||||||
if (exitCode == Messages.OK) {
|
|
||||||
ZigDebuggerSettings.instance.downloadAutomatically = isSelected
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return withEDTContext(ModalityState.any()) {
|
|
||||||
MessageDialogBuilder
|
|
||||||
.okCancel(ZigDebugBundle.message("debugger.run.unavailable"), message)
|
|
||||||
.yesText(action)
|
|
||||||
.icon(Messages.getErrorIcon())
|
|
||||||
.doNotAsk(doNotAsk)
|
|
||||||
.ask(project)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private open class ZigLLDBDriverConfiguration(private val isElevated: Boolean, private val emulateTerminal: Boolean): LLDBDriverConfiguration() {
|
|
||||||
override fun getDriverName() = "Zig LLDB"
|
|
||||||
override fun isElevated() = isElevated
|
|
||||||
override fun emulateTerminal() = emulateTerminal
|
|
||||||
}
|
|
||||||
private class ZigCustomBinariesLLDBDriverConfiguration(
|
|
||||||
private val binaries: LLDBBinaries,
|
|
||||||
isElevated: Boolean,
|
|
||||||
emulateTerminal: Boolean
|
|
||||||
) : ZigLLDBDriverConfiguration(isElevated, emulateTerminal) {
|
|
||||||
override fun useSTLRenderers() = false
|
|
||||||
override fun getLLDBFrameworkFile(architectureType: ArchitectureType): File = binaries.frameworkFile.toFile()
|
|
||||||
override fun getLLDBFrontendFile(architectureType: ArchitectureType): File = binaries.frontendFile.toFile()
|
|
||||||
}
|
|
||||||
|
|
||||||
private open class ZigGDBDriverConfiguration(private val isElevated: Boolean, private val emulateTerminal: Boolean): GDBDriverConfiguration() {
|
|
||||||
override fun getDriverName() = "Zig GDB"
|
|
||||||
override fun isAttachSupported() = false
|
|
||||||
override fun isElevated() = isElevated
|
|
||||||
override fun emulateTerminal() = emulateTerminal
|
|
||||||
}
|
|
||||||
private class ZigCustomBinariesGDBDriverConfiguration(
|
|
||||||
private val binaries: GDBBinaries,
|
|
||||||
isElevated: Boolean,
|
|
||||||
emulateTerminal: Boolean
|
|
||||||
) : ZigGDBDriverConfiguration(isElevated, emulateTerminal) {
|
|
||||||
override fun getGDBExecutablePath() = binaries.gdbFile.pathString
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ZigMSVCDriverConfiguration(
|
|
||||||
private val binaries: MSVCBinaries,
|
|
||||||
private val isElevated: Boolean,
|
|
||||||
private val emulateTerminal: Boolean
|
|
||||||
): MSVCDriverConfiguration() {
|
|
||||||
override val debuggerExecutable get() = binaries.msvcFile
|
|
||||||
override fun getDriverName() = "Zig MSVC"
|
|
||||||
override fun getConsoleLanguage() = ZigLanguage
|
|
||||||
override fun isElevated() = isElevated
|
|
||||||
override fun emulateTerminal() = emulateTerminal
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.zig.ZigFileType
|
|
||||||
import com.intellij.openapi.fileTypes.FileType
|
|
||||||
import com.jetbrains.cidr.execution.debugger.breakpoints.CidrLineBreakpointFileTypesProvider
|
|
||||||
|
|
||||||
class ZigLineBreakpointFileTypesProvider: CidrLineBreakpointFileTypesProvider {
|
|
||||||
override fun getFileTypes(): Set<FileType> {
|
|
||||||
return setOf(ZigFileType)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger
|
|
||||||
|
|
||||||
import com.intellij.execution.filters.Filter
|
|
||||||
import com.intellij.execution.filters.TextConsoleBuilder
|
|
||||||
import com.intellij.xdebugger.XDebugSession
|
|
||||||
import com.jetbrains.cidr.execution.RunParameters
|
|
||||||
import com.jetbrains.cidr.execution.debugger.CidrLocalDebugProcess
|
|
||||||
|
|
||||||
class ZigLocalDebugProcess(parameters: RunParameters, session: XDebugSession, consoleBuilder: TextConsoleBuilder) : CidrLocalDebugProcess(parameters, session, consoleBuilder, { Filter.EMPTY_ARRAY }, true)
|
|
|
@ -1,49 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.shared.zigCoroutineScope
|
|
||||||
import com.falsepattern.zigbrains.zig.ZigFileType
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.xdebugger.XSourcePosition
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.LLValue
|
|
||||||
import com.jetbrains.cidr.execution.debugger.evaluation.LocalVariablesFilterHandler
|
|
||||||
import kotlinx.coroutines.async
|
|
||||||
import kotlinx.coroutines.future.asCompletableFuture
|
|
||||||
import java.util.concurrent.CompletableFuture
|
|
||||||
|
|
||||||
class ZigLocalVariablesFilterHandler: LocalVariablesFilterHandler {
|
|
||||||
override fun filterVars(proj: Project, pos: XSourcePosition, vars: List<LLValue>): CompletableFuture<List<LLValue>> {
|
|
||||||
return proj.zigCoroutineScope.async {
|
|
||||||
val vf = pos.file
|
|
||||||
if (vf.fileType == ZigFileType) {
|
|
||||||
return@async ArrayList(vars)
|
|
||||||
}
|
|
||||||
return@async listOf()
|
|
||||||
}.asCompletableFuture()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canFilterAtPos(proj: Project, pos: XSourcePosition): Boolean {
|
|
||||||
return pos.file.fileType == ZigFileType
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.dap
|
|
||||||
|
|
||||||
import java.io.IOException
|
|
||||||
import java.io.InterruptedIOException
|
|
||||||
import java.io.PipedInputStream
|
|
||||||
import java.io.PipedOutputStream
|
|
||||||
|
|
||||||
class BlockingPipedInputStream(src: PipedOutputStream, pipeSize: Int) : PipedInputStream(src, pipeSize) {
|
|
||||||
var closed = false
|
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
override fun read(): Int {
|
|
||||||
if (closed) {
|
|
||||||
throw IOException("stream closed")
|
|
||||||
} else {
|
|
||||||
while (super.`in` < 0) {
|
|
||||||
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
|
|
||||||
this as java.lang.Object
|
|
||||||
|
|
||||||
this.notifyAll()
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.wait(750)
|
|
||||||
} catch (e: InterruptedException) {
|
|
||||||
throw InterruptedIOException()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val ret = buffer[this.out++].toUInt()
|
|
||||||
if (this.out >= buffer.size) {
|
|
||||||
this.out = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.`in` == this.out) {
|
|
||||||
this.`in` = -1
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret.toInt()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun close() {
|
|
||||||
closed = true
|
|
||||||
super.close()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.dap
|
|
||||||
|
|
||||||
import com.intellij.openapi.util.Expirable
|
|
||||||
import com.intellij.openapi.util.Pair
|
|
||||||
import com.intellij.openapi.util.UserDataHolderEx
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.*
|
|
||||||
import org.eclipse.lsp4j.debug.InitializeRequestArguments
|
|
||||||
|
|
||||||
abstract class DAPDebuggerDriverConfiguration: DebuggerDriverConfiguration() {
|
|
||||||
override fun createEvaluationContext(driver: DebuggerDriver, expirable: Expirable?, llThread: LLThread, llFrame: LLFrame, data: UserDataHolderEx): EvaluationContext {
|
|
||||||
return object : EvaluationContext(driver, expirable, llThread, llFrame, data) {
|
|
||||||
override fun convertToRValue(data: LLValueData, pair: Pair<LLValue, String>): String {
|
|
||||||
return cast(pair.second, pair.first?.type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun customizeInitializeArguments(initArgs: InitializeRequestArguments)
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,262 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package com.falsepattern.zigbrains.debugger.dap
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.ZigDebuggerLanguage
|
|
||||||
import com.intellij.openapi.application.readAction
|
|
||||||
import com.intellij.openapi.editor.Document
|
|
||||||
import com.intellij.openapi.vfs.VfsUtil
|
|
||||||
import com.intellij.openapi.vfs.findDocument
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.*
|
|
||||||
import com.jetbrains.cidr.execution.debugger.memory.Address
|
|
||||||
import com.jetbrains.cidr.execution.debugger.memory.AddressRange
|
|
||||||
import org.eclipse.lsp4j.debug.*
|
|
||||||
import java.nio.file.InvalidPathException
|
|
||||||
import java.nio.file.Path
|
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.CompletableFuture
|
|
||||||
import java.util.concurrent.ExecutionException
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import java.util.concurrent.TimeoutException
|
|
||||||
import java.util.regex.Pattern
|
|
||||||
|
|
||||||
object Util {
|
|
||||||
fun threadJBFromDAP(DAPThread: Thread): LLThread {
|
|
||||||
return LLThread(DAPThread.id.toLong(), null, null, DAPThread.name, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun threadDAPFromJB(JBThread: LLThread): Thread {
|
|
||||||
val DAPThread = Thread()
|
|
||||||
DAPThread.id = JBThread.getId().toInt()
|
|
||||||
return DAPThread
|
|
||||||
}
|
|
||||||
|
|
||||||
fun breakpointJBFromDAP(DAPBreakpoint: Breakpoint): LLBreakpoint {
|
|
||||||
val source = DAPBreakpoint.source
|
|
||||||
var sourcePath = if (source == null) "" else Objects.requireNonNullElseGet(
|
|
||||||
source.path
|
|
||||||
) { Objects.requireNonNullElse(source.origin, "unknown") }
|
|
||||||
sourcePath = toJBPath(sourcePath)
|
|
||||||
return LLBreakpoint(
|
|
||||||
DAPBreakpoint.id,
|
|
||||||
sourcePath,
|
|
||||||
Objects.requireNonNullElse<Int>(DAPBreakpoint.line, 0) - 1,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getLocation(DAPBreakpoint: Breakpoint): LLBreakpointLocation? {
|
|
||||||
val ref = DAPBreakpoint.instructionReference ?: return null
|
|
||||||
val addr = ref.substring(2).toLong(16)
|
|
||||||
var fl: FileLocation? = null
|
|
||||||
val src = DAPBreakpoint.source
|
|
||||||
if (src != null) {
|
|
||||||
fl = FileLocation(src.path, DAPBreakpoint.line)
|
|
||||||
}
|
|
||||||
return LLBreakpointLocation(DAPBreakpoint.id.toString() + "", Address.fromUnsignedLong(addr), fl)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun breakpointDAPFromJB(JBBreakpoint: LLBreakpoint): Breakpoint {
|
|
||||||
val DAPBreakpoint = Breakpoint()
|
|
||||||
DAPBreakpoint.id = JBBreakpoint.getId()
|
|
||||||
DAPBreakpoint.line = JBBreakpoint.getOrigLine() + 1
|
|
||||||
val source = Source()
|
|
||||||
source.path = JBBreakpoint.getOrigFile()
|
|
||||||
DAPBreakpoint.source = source
|
|
||||||
DAPBreakpoint.message = JBBreakpoint.getCondition()
|
|
||||||
return DAPBreakpoint
|
|
||||||
}
|
|
||||||
|
|
||||||
fun moduleJBFromDAP(DAPModule: Module): LLModule {
|
|
||||||
return LLModule(toJBPath(DAPModule.path))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun moduleDAPFromJB(JBModule: LLModule): Module {
|
|
||||||
val DAPModule = Module()
|
|
||||||
DAPModule.path = toJBPath(JBModule.path)
|
|
||||||
DAPModule.name = JBModule.name
|
|
||||||
return DAPModule
|
|
||||||
}
|
|
||||||
|
|
||||||
fun frameJBFromDAP(
|
|
||||||
DAPFrame: StackFrame,
|
|
||||||
helperBreakpoint: DAPDriver.MappedBreakpoint?,
|
|
||||||
modules: Map<Int, DAPDriver.MappedModule>
|
|
||||||
): LLFrame {
|
|
||||||
val ptr = parseAddress(DAPFrame.instructionPointerReference)
|
|
||||||
val name = DAPFrame.name
|
|
||||||
val inline = name.startsWith("[Inline Frame] ")
|
|
||||||
val function = name.substring(name.indexOf('!') + 1, name.indexOf('('))
|
|
||||||
val moduleID = DAPFrame.moduleId
|
|
||||||
var moduleName: String? = null
|
|
||||||
if (moduleID != null) {
|
|
||||||
if (moduleID.isRight) {
|
|
||||||
moduleName = moduleID.right
|
|
||||||
} else {
|
|
||||||
val module = modules[moduleID.left]!!
|
|
||||||
moduleName = module.java.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var line = DAPFrame.line
|
|
||||||
var sourcePath: String?
|
|
||||||
run {
|
|
||||||
val src = DAPFrame.source
|
|
||||||
sourcePath = if (src == null) null else toJBPath(src.path)
|
|
||||||
}
|
|
||||||
if (helperBreakpoint != null) {
|
|
||||||
if (line == 0) {
|
|
||||||
line = helperBreakpoint.dap.line
|
|
||||||
}
|
|
||||||
if (sourcePath == null) {
|
|
||||||
val src = helperBreakpoint.dap.source
|
|
||||||
if (src != null) {
|
|
||||||
sourcePath = toJBPath(src.path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return LLFrame(
|
|
||||||
DAPFrame.id,
|
|
||||||
function,
|
|
||||||
sourcePath,
|
|
||||||
null,
|
|
||||||
line - 1,
|
|
||||||
ptr,
|
|
||||||
ZigDebuggerLanguage,
|
|
||||||
false,
|
|
||||||
inline,
|
|
||||||
moduleName
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toSource(path: String): Source {
|
|
||||||
val src = Source()
|
|
||||||
val absolute = Path.of(path).toAbsolutePath()
|
|
||||||
src.name = absolute.fileName.toString()
|
|
||||||
src.path = toWinPath(absolute.toString())
|
|
||||||
return src
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toWinPath(path: String): String {
|
|
||||||
return path.replace('/', '\\')
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toJBPath(path: String): String {
|
|
||||||
return path.replace('\\', '/')
|
|
||||||
}
|
|
||||||
|
|
||||||
fun parseAddressNullable(address: String?): Long? {
|
|
||||||
if (address == null) return null
|
|
||||||
return parseAddress(address)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun parseAddress(address: String?): Long {
|
|
||||||
if (address == null) return 0L
|
|
||||||
if (!address.startsWith("0x")) return java.lang.Long.parseUnsignedLong(address)
|
|
||||||
return java.lang.Long.parseUnsignedLong(address.substring(2), 16)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun stringifyAddress(address: Long): String {
|
|
||||||
return "0x" + java.lang.Long.toHexString(address)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val HEX_FIX_REGEX: Pattern = Pattern.compile("([0-9A-F]+)(?<!\\W)h")
|
|
||||||
suspend fun instructionJBFromDAP(
|
|
||||||
DAPInstruction: DisassembledInstruction,
|
|
||||||
loc: Source?,
|
|
||||||
startLineIn: Int?,
|
|
||||||
endLineIn: Int?,
|
|
||||||
uniq: Boolean,
|
|
||||||
symbol: LLSymbolOffset?
|
|
||||||
): LLInstruction {
|
|
||||||
var startLine = startLineIn
|
|
||||||
var endLine = endLineIn
|
|
||||||
val address: Address = Address.parseHexString(DAPInstruction.address)
|
|
||||||
val byteStrings =
|
|
||||||
DAPInstruction.instructionBytes.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
|
||||||
val bytes = ArrayList<Byte>(byteStrings.size)
|
|
||||||
for (byteString in byteStrings) {
|
|
||||||
bytes.add(byteString.toInt(16).toByte())
|
|
||||||
}
|
|
||||||
var comment: String? = null
|
|
||||||
if (loc != null && startLine != null && endLine != null && uniq) run {
|
|
||||||
val pathStr = toJBPath(loc.path)
|
|
||||||
val path: Path
|
|
||||||
try {
|
|
||||||
path = Path.of(pathStr)
|
|
||||||
} catch (ignored: InvalidPathException) {
|
|
||||||
return@run
|
|
||||||
}
|
|
||||||
val text = readAction {
|
|
||||||
val file = VfsUtil.findFile(path, true) ?: return@readAction null
|
|
||||||
val doc: Document = file.findDocument() ?: return@readAction null
|
|
||||||
doc.immutableCharSequence.toString().split("(\r\n|\r|\n)".toRegex()).dropLastWhile { it.isEmpty() }
|
|
||||||
.toTypedArray()
|
|
||||||
}
|
|
||||||
if (text == null) return@run
|
|
||||||
startLine -= 1
|
|
||||||
endLine -= 1
|
|
||||||
if (text.size <= endLine) return@run
|
|
||||||
comment = text[endLine]
|
|
||||||
}
|
|
||||||
val nicerDisassembly = StringBuilder()
|
|
||||||
val disassembly = DAPInstruction.instruction
|
|
||||||
val matcher = HEX_FIX_REGEX.matcher(disassembly)
|
|
||||||
var prevEnd = 0
|
|
||||||
while (matcher.find()) {
|
|
||||||
nicerDisassembly.append(disassembly, prevEnd, matcher.start())
|
|
||||||
val hex = matcher.group(1).lowercase(Locale.getDefault())
|
|
||||||
nicerDisassembly.append("0x").append(hex)
|
|
||||||
prevEnd = matcher.end()
|
|
||||||
}
|
|
||||||
if (prevEnd < disassembly.length) nicerDisassembly.append(disassembly, prevEnd, disassembly.length)
|
|
||||||
return LLInstruction.create(
|
|
||||||
address,
|
|
||||||
bytes,
|
|
||||||
nicerDisassembly.toString(),
|
|
||||||
comment,
|
|
||||||
symbol
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun memoryJBFromDAP(DAPMemory: ReadMemoryResponse): LLMemoryHunk {
|
|
||||||
val address = parseAddress(DAPMemory.address)
|
|
||||||
val bytes = Base64.getDecoder().decode(DAPMemory.data)
|
|
||||||
val range = AddressRange(
|
|
||||||
Address.fromUnsignedLong(address),
|
|
||||||
Address.fromUnsignedLong(address + bytes.size - 1)
|
|
||||||
)
|
|
||||||
return LLMemoryHunk(range, bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(com.intellij.execution.ExecutionException::class)
|
|
||||||
fun <T> get(future: CompletableFuture<T>): T {
|
|
||||||
try {
|
|
||||||
return future[4, TimeUnit.SECONDS]
|
|
||||||
} catch (e: InterruptedException) {
|
|
||||||
throw com.intellij.execution.ExecutionException(e)
|
|
||||||
} catch (e: TimeoutException) {
|
|
||||||
throw com.intellij.execution.ExecutionException(e)
|
|
||||||
} catch (e: ExecutionException) {
|
|
||||||
throw com.intellij.execution.ExecutionException(e.cause)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.execution.binary
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.Icons
|
|
||||||
import com.falsepattern.zigbrains.debugger.ZigDebugBundle
|
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
|
||||||
import com.intellij.execution.configurations.ConfigurationTypeBase
|
|
||||||
import com.intellij.execution.configurations.RunConfiguration
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
|
|
||||||
class ZigConfigTypeBinary: ConfigurationTypeBase(
|
|
||||||
IDENTIFIER,
|
|
||||||
ZigDebugBundle.message("configuration.binary.name"),
|
|
||||||
ZigDebugBundle.message("configuration.binary.description"),
|
|
||||||
Icons.Zig
|
|
||||||
) {
|
|
||||||
init {
|
|
||||||
addFactory(ConfigFactoryBinary(this))
|
|
||||||
}
|
|
||||||
class ConfigFactoryBinary(type: ZigConfigTypeBinary): ConfigurationFactory(type) {
|
|
||||||
override fun createTemplateConfiguration(project: Project): RunConfiguration {
|
|
||||||
return ZigExecConfigBinary(project, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getId(): String {
|
|
||||||
return IDENTIFIER
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private const val IDENTIFIER = "ZIGBRAINS_BINARY"
|
|
|
@ -1,59 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.execution.binary
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.ZigDebugBundle
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.*
|
|
||||||
import com.intellij.execution.Executor
|
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
|
||||||
import com.intellij.execution.runners.ExecutionEnvironment
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
|
|
||||||
class ZigExecConfigBinary(project: Project, factory: ConfigurationFactory) : ZigExecConfig<ZigExecConfigBinary>(project, factory, ZigDebugBundle.message("exec.type.binary.label")) {
|
|
||||||
var exePath = FilePathConfigurable("exePath", ZigDebugBundle.message("exec.option.label.binary.exe-path"))
|
|
||||||
private set
|
|
||||||
var args = ArgsConfigurable("args", ZigDebugBundle.message("exec.option.label.binary.args"))
|
|
||||||
private set
|
|
||||||
|
|
||||||
override val suggestedName: String
|
|
||||||
get() = ZigDebugBundle.message("configuration.binary.suggested-name")
|
|
||||||
|
|
||||||
override suspend fun buildCommandLineArgs(debug: Boolean): List<String> {
|
|
||||||
return args.argsSplit()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getConfigurables(): List<ZigConfigurable<*>> {
|
|
||||||
return super.getConfigurables() + listOf(exePath, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getState(executor: Executor, environment: ExecutionEnvironment): ZigProfileState<ZigExecConfigBinary> {
|
|
||||||
return ZigProfileStateBinary(environment, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clone(): ZigExecConfigBinary {
|
|
||||||
val clone = super.clone()
|
|
||||||
clone.exePath = exePath.clone()
|
|
||||||
clone.args = args.clone()
|
|
||||||
return clone
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.execution.binary
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.ZigDebugBundle
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigProfileState
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
|
||||||
import com.intellij.execution.ExecutionException
|
|
||||||
import com.intellij.execution.configurations.GeneralCommandLine
|
|
||||||
import com.intellij.execution.runners.ExecutionEnvironment
|
|
||||||
import kotlin.io.path.pathString
|
|
||||||
|
|
||||||
class ZigProfileStateBinary(environment: ExecutionEnvironment, configuration: ZigExecConfigBinary) : ZigProfileState<ZigExecConfigBinary>(environment, configuration) {
|
|
||||||
override suspend fun getCommandLine(toolchain: ZigToolchain, debug: Boolean): GeneralCommandLine {
|
|
||||||
val cli = GeneralCommandLine()
|
|
||||||
val cfg = configuration
|
|
||||||
cfg.workingDirectory.path?.let { cli.withWorkingDirectory(it) }
|
|
||||||
cli.withExePath(cfg.exePath.path?.pathString ?: throw ExecutionException(ZigDebugBundle.message("exception.missing-exe-path")))
|
|
||||||
cli.withCharset(Charsets.UTF_8)
|
|
||||||
cli.addParameters(cfg.args.args)
|
|
||||||
return cli
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.runner.base
|
|
||||||
|
|
||||||
import com.intellij.execution.ExecutionException
|
|
||||||
|
|
||||||
interface PreLaunchAware {
|
|
||||||
@Throws(ExecutionException::class)
|
|
||||||
suspend fun preLaunch(listener: PreLaunchProcessListener)
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.runner.base
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.project.run.ZigProcessHandler
|
|
||||||
import com.falsepattern.zigbrains.shared.cli.startIPCAwareProcess
|
|
||||||
import com.intellij.execution.ExecutionException
|
|
||||||
import com.intellij.execution.configurations.GeneralCommandLine
|
|
||||||
import com.intellij.execution.process.ProcessEvent
|
|
||||||
import com.intellij.execution.process.ProcessHandler
|
|
||||||
import com.intellij.execution.process.ProcessListener
|
|
||||||
import com.intellij.execution.ui.ConsoleView
|
|
||||||
import com.intellij.execution.ui.ConsoleViewContentType
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.platform.util.progress.withProgressText
|
|
||||||
import com.intellij.util.io.awaitExit
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.runInterruptible
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
class PreLaunchProcessListener(val console: ConsoleView) : ProcessListener {
|
|
||||||
var isBuildFailed: Boolean = false
|
|
||||||
private set
|
|
||||||
lateinit var processHandler: ZigProcessHandler.IPCAware
|
|
||||||
private set
|
|
||||||
|
|
||||||
@Throws(ExecutionException::class)
|
|
||||||
suspend fun executeCommandLineWithHook(project: Project, commandLine: GeneralCommandLine): Boolean {
|
|
||||||
return withProgressText(commandLine.commandLineString) {
|
|
||||||
val processHandler = commandLine.startIPCAwareProcess(project)
|
|
||||||
this@PreLaunchProcessListener.processHandler = processHandler
|
|
||||||
hook(processHandler)
|
|
||||||
processHandler.startNotify()
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
processHandler.process.awaitExit()
|
|
||||||
}
|
|
||||||
runInterruptible {
|
|
||||||
processHandler.waitFor()
|
|
||||||
}
|
|
||||||
return@withProgressText isBuildFailed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun hook(handler: ProcessHandler) {
|
|
||||||
console.attachToProcess(handler)
|
|
||||||
handler.addProcessListener(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun processTerminated(event: ProcessEvent) {
|
|
||||||
if (event.exitCode != 0) {
|
|
||||||
isBuildFailed = true
|
|
||||||
} else {
|
|
||||||
isBuildFailed = false
|
|
||||||
console.print("Build Successful. Starting debug session. \n", ConsoleViewContentType.NORMAL_OUTPUT)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.runner.base
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigProfileState
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
|
||||||
import com.falsepattern.zigbrains.shared.zigCoroutineScope
|
|
||||||
import com.intellij.execution.configurations.GeneralCommandLine
|
|
||||||
import com.intellij.execution.configurations.PtyCommandLine
|
|
||||||
import com.jetbrains.cidr.execution.Installer
|
|
||||||
import kotlinx.coroutines.async
|
|
||||||
import kotlinx.coroutines.future.asCompletableFuture
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class ZigDebugEmitBinaryInstaller<ProfileState: ZigProfileState<*>>(
|
|
||||||
private val profileState: ProfileState,
|
|
||||||
private val toolchain: ZigToolchain,
|
|
||||||
private val executableFile: File,
|
|
||||||
private val exeArgs: List<String>
|
|
||||||
): Installer {
|
|
||||||
override fun install(): GeneralCommandLine {
|
|
||||||
val cfg = profileState.configuration
|
|
||||||
val cli = PtyCommandLine().withConsoleMode(false).withExePath(executableFile.absolutePath)
|
|
||||||
cfg.workingDirectory.path?.let { x -> cli.withWorkingDirectory(x) }
|
|
||||||
cli.addParameters(exeArgs)
|
|
||||||
cli.withCharset(Charsets.UTF_8)
|
|
||||||
cli.withRedirectErrorStream(true)
|
|
||||||
return profileState.configuration.project.zigCoroutineScope.async{
|
|
||||||
profileState.configuration.patchCommandLine(cli)
|
|
||||||
}.asCompletableFuture().join()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getExecutableFile(): File {
|
|
||||||
return executableFile
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.runner.base
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigProfileState
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
|
||||||
import com.intellij.util.system.CpuArch
|
|
||||||
import com.jetbrains.cidr.ArchitectureType
|
|
||||||
import com.jetbrains.cidr.execution.RunParameters
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
|
|
||||||
|
|
||||||
abstract class ZigDebugParametersBase<ProfileState: ZigProfileState<*>>(
|
|
||||||
private val driverConfiguration: DebuggerDriverConfiguration,
|
|
||||||
protected val toolchain: ZigToolchain,
|
|
||||||
protected val profileState: ProfileState
|
|
||||||
): RunParameters() {
|
|
||||||
override fun getDebuggerDriverConfiguration(): DebuggerDriverConfiguration {
|
|
||||||
return driverConfiguration
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getArchitectureId(): String {
|
|
||||||
return ArchitectureType.forVmCpuArch(CpuArch.CURRENT).id
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.runner.base
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.ZigDebugBundle
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigProfileState
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
|
||||||
import com.intellij.execution.ExecutionException
|
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
|
||||||
import com.intellij.openapi.util.io.toNioPathOrNull
|
|
||||||
import com.intellij.platform.util.progress.withProgressText
|
|
||||||
import com.intellij.util.containers.orNull
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import java.io.File
|
|
||||||
import java.nio.file.Files
|
|
||||||
import kotlin.io.path.absolutePathString
|
|
||||||
import kotlin.io.path.isExecutable
|
|
||||||
import kotlin.io.path.pathString
|
|
||||||
|
|
||||||
abstract class ZigDebugParametersEmitBinaryBase<ProfileState: ZigProfileState<*>>(
|
|
||||||
driverConfiguration: DebuggerDriverConfiguration,
|
|
||||||
toolchain: ZigToolchain,
|
|
||||||
profileState: ProfileState,
|
|
||||||
) : ZigDebugParametersBase<ProfileState>(driverConfiguration, toolchain, profileState), PreLaunchAware {
|
|
||||||
@Volatile
|
|
||||||
protected lateinit var executableFile: File
|
|
||||||
private set
|
|
||||||
|
|
||||||
@Throws(ExecutionException::class)
|
|
||||||
private suspend fun compileExe(listener: PreLaunchProcessListener): File {
|
|
||||||
val commandLine = profileState.getCommandLine(toolchain, true)
|
|
||||||
val cliString = commandLine.getCommandLineString(commandLine.exePath.toNioPathOrNull()?.fileName?.pathString)
|
|
||||||
val tmpDir = FileUtil.createTempDirectory("zigbrains_debug", "", true).toPath()
|
|
||||||
|
|
||||||
val exe = tmpDir.resolve("executable")
|
|
||||||
commandLine.addParameters("-femit-bin=${exe.absolutePathString()}")
|
|
||||||
|
|
||||||
if (listener.executeCommandLineWithHook(profileState.environment.project, commandLine))
|
|
||||||
throw ExecutionException(ZigDebugBundle.message("debug.base.compile.failed.generic", cliString))
|
|
||||||
|
|
||||||
return withContext(Dispatchers.IO) {
|
|
||||||
Files.list(tmpDir).use { stream ->
|
|
||||||
stream.filter { !it.fileName.endsWith(".o") }
|
|
||||||
.filter { it.isExecutable() }
|
|
||||||
.findFirst()
|
|
||||||
.map { it.toFile() }
|
|
||||||
.orNull()
|
|
||||||
}
|
|
||||||
} ?: throw ExecutionException(ZigDebugBundle.message("debug.base.compile.failed.no-exe"))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(ExecutionException::class)
|
|
||||||
override suspend fun preLaunch(listener: PreLaunchProcessListener) {
|
|
||||||
this.executableFile = withProgressText("Compiling executable") {
|
|
||||||
compileExe(listener)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,135 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.runner.base
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugbridge.ZigDebuggerDriverConfigurationProviderBase
|
|
||||||
import com.falsepattern.zigbrains.debugger.ZigLocalDebugProcess
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.build.ZigDebugRunnerBuild
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigProfileState
|
|
||||||
import com.falsepattern.zigbrains.project.run.ZigProgramRunner
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
|
||||||
import com.falsepattern.zigbrains.shared.coroutine.runInterruptibleEDT
|
|
||||||
import com.falsepattern.zigbrains.shared.coroutine.withEDTContext
|
|
||||||
import com.intellij.execution.DefaultExecutionResult
|
|
||||||
import com.intellij.execution.ExecutionException
|
|
||||||
import com.intellij.execution.executors.DefaultDebugExecutor
|
|
||||||
import com.intellij.execution.filters.Filter
|
|
||||||
import com.intellij.execution.filters.TextConsoleBuilder
|
|
||||||
import com.intellij.execution.process.ProcessTerminatedListener
|
|
||||||
import com.intellij.execution.runners.ExecutionEnvironment
|
|
||||||
import com.intellij.execution.runners.RunContentBuilder
|
|
||||||
import com.intellij.execution.ui.ConsoleView
|
|
||||||
import com.intellij.execution.ui.ConsoleViewContentType
|
|
||||||
import com.intellij.execution.ui.RunContentDescriptor
|
|
||||||
import com.intellij.openapi.application.ModalityState
|
|
||||||
import com.intellij.openapi.project.guessProjectDir
|
|
||||||
import com.intellij.platform.util.progress.reportProgress
|
|
||||||
import com.intellij.xdebugger.XDebugProcess
|
|
||||||
import com.intellij.xdebugger.XDebugProcessStarter
|
|
||||||
import com.intellij.xdebugger.XDebugSession
|
|
||||||
import com.intellij.xdebugger.XDebuggerManager
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
|
|
||||||
|
|
||||||
abstract class ZigDebugRunnerBase<ProfileState : ZigProfileState<*>> : ZigProgramRunner<ProfileState>(DefaultDebugExecutor.EXECUTOR_ID) {
|
|
||||||
@Throws(ExecutionException::class)
|
|
||||||
override suspend fun execute(
|
|
||||||
state: ProfileState,
|
|
||||||
toolchain: ZigToolchain,
|
|
||||||
environment: ExecutionEnvironment
|
|
||||||
): RunContentDescriptor? {
|
|
||||||
val project = environment.project
|
|
||||||
val driverProviders = ZigDebuggerDriverConfigurationProviderBase.EXTENSION_POINT_NAME.extensionList
|
|
||||||
for (provider in driverProviders) {
|
|
||||||
val driver = provider.getDebuggerConfiguration(project, isElevated = false, emulateTerminal = true, DebuggerDriverConfiguration::class.java) ?: continue
|
|
||||||
return executeWithDriver(state, toolchain, environment, driver) ?: continue
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(ExecutionException::class)
|
|
||||||
private suspend fun executeWithDriver(
|
|
||||||
state: ProfileState,
|
|
||||||
toolchain: ZigToolchain,
|
|
||||||
environment: ExecutionEnvironment,
|
|
||||||
debuggerDriver: DebuggerDriverConfiguration
|
|
||||||
): RunContentDescriptor? {
|
|
||||||
return reportProgress { reporter ->
|
|
||||||
val runParameters = getDebugParameters(state, debuggerDriver, toolchain)
|
|
||||||
val console = state.consoleBuilder.console
|
|
||||||
if (runParameters is PreLaunchAware) {
|
|
||||||
val listener = PreLaunchProcessListener(console)
|
|
||||||
try {
|
|
||||||
reporter.indeterminateStep {
|
|
||||||
runParameters.preLaunch(listener)
|
|
||||||
}
|
|
||||||
} catch (e: ExecutionException) {
|
|
||||||
console.print("\n", ConsoleViewContentType.ERROR_OUTPUT)
|
|
||||||
e.message?.let { listener.console.print(it, ConsoleViewContentType.ERROR_OUTPUT) }
|
|
||||||
if (this !is ZigDebugRunnerBuild && environment.project.guessProjectDir()?.children?.any { it.name == "build.zig" } == true) {
|
|
||||||
console.print("\n Warning: build.zig file detected in project.\n Did you want to use a Zig Build task instead?", ConsoleViewContentType.ERROR_OUTPUT)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (listener.isBuildFailed) {
|
|
||||||
val executionResult = DefaultExecutionResult(console, listener.processHandler.unwrap())
|
|
||||||
return@reportProgress withEDTContext(ModalityState.any()) {
|
|
||||||
val runContentBuilder = RunContentBuilder(executionResult, environment)
|
|
||||||
runContentBuilder.showRunContent(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return@reportProgress runInterruptibleEDT(ModalityState.any()) {
|
|
||||||
val debuggerManager = XDebuggerManager.getInstance(environment.project)
|
|
||||||
debuggerManager.startSession(environment, object: XDebugProcessStarter() {
|
|
||||||
override fun start(session: XDebugSession): XDebugProcess {
|
|
||||||
val project = session.project
|
|
||||||
val textConsoleBuilder = state.consoleBuilder
|
|
||||||
val debugProcess = ZigLocalDebugProcess(runParameters, session, textConsoleBuilder)
|
|
||||||
ProcessTerminatedListener.attach(debugProcess.processHandler, project)
|
|
||||||
debugProcess.start()
|
|
||||||
return debugProcess
|
|
||||||
}
|
|
||||||
}).runContentDescriptor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(ExecutionException::class)
|
|
||||||
protected abstract fun getDebugParameters(
|
|
||||||
state: ProfileState,
|
|
||||||
debuggerDriver: DebuggerDriverConfiguration,
|
|
||||||
toolchain: ZigToolchain
|
|
||||||
): ZigDebugParametersBase<ProfileState>
|
|
||||||
|
|
||||||
private class SharedConsoleBuilder(private val console: ConsoleView) : TextConsoleBuilder() {
|
|
||||||
override fun getConsole(): ConsoleView {
|
|
||||||
return console
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun addFilter(filter: Filter) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setViewer(isViewer: Boolean) {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.runner.binary
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.ZigDebugBundle
|
|
||||||
import com.falsepattern.zigbrains.debugger.execution.binary.ZigProfileStateBinary
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugEmitBinaryInstaller
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersBase
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
|
||||||
import com.intellij.execution.ExecutionException
|
|
||||||
import com.jetbrains.cidr.execution.Installer
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
|
|
||||||
|
|
||||||
|
|
||||||
class ZigDebugParametersBinary @Throws(ExecutionException::class) constructor(driverConfiguration: DebuggerDriverConfiguration, toolchain: ZigToolchain, profileState: ZigProfileStateBinary) :
|
|
||||||
ZigDebugParametersBase<ZigProfileStateBinary>(driverConfiguration, toolchain, profileState) {
|
|
||||||
private val executableFile = profileState.configuration.exePath.path?.toFile() ?: throw ExecutionException(ZigDebugBundle.message("exception.missing-exe-path"))
|
|
||||||
override fun getInstaller(): Installer {
|
|
||||||
return ZigDebugEmitBinaryInstaller(profileState, toolchain, executableFile, profileState.configuration.args.argsSplit())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.runner.binary
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.execution.binary.ZigExecConfigBinary
|
|
||||||
import com.falsepattern.zigbrains.debugger.execution.binary.ZigProfileStateBinary
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersBase
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugRunnerBase
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigProfileState
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.local.LocalZigToolchain
|
|
||||||
import com.intellij.execution.configurations.RunProfile
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
|
|
||||||
|
|
||||||
class ZigDebugRunnerBinary: ZigDebugRunnerBase<ZigProfileStateBinary>() {
|
|
||||||
override fun getDebugParameters(
|
|
||||||
state: ZigProfileStateBinary,
|
|
||||||
debuggerDriver: DebuggerDriverConfiguration,
|
|
||||||
toolchain: ZigToolchain
|
|
||||||
): ZigDebugParametersBase<ZigProfileStateBinary> {
|
|
||||||
return ZigDebugParametersBinary(debuggerDriver, LocalZigToolchain.ensureLocal(toolchain), state)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun castProfileState(state: ZigProfileState<*>): ZigProfileStateBinary? {
|
|
||||||
return state as? ZigProfileStateBinary
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canRun(executorId: String, profile: RunProfile): Boolean {
|
|
||||||
return this.executorId == executorId && profile is ZigExecConfigBinary
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getRunnerId(): String {
|
|
||||||
return "ZigDebugRunnerBinary"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,115 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.runner.build
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.ZigDebugBundle
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.PreLaunchAware
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.PreLaunchProcessListener
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugEmitBinaryInstaller
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersBase
|
|
||||||
import com.falsepattern.zigbrains.project.execution.build.ZigProfileStateBuild
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
|
||||||
import com.intellij.execution.ExecutionException
|
|
||||||
import com.intellij.openapi.util.SystemInfo
|
|
||||||
import com.intellij.platform.util.progress.withProgressText
|
|
||||||
import com.jetbrains.cidr.execution.Installer
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import org.jetbrains.annotations.PropertyKey
|
|
||||||
import java.io.File
|
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
|
||||||
import java.util.stream.Stream
|
|
||||||
import kotlin.io.path.isExecutable
|
|
||||||
import kotlin.io.path.isRegularFile
|
|
||||||
|
|
||||||
class ZigDebugParametersBuild(
|
|
||||||
driverConfiguration: DebuggerDriverConfiguration,
|
|
||||||
toolchain: ZigToolchain,
|
|
||||||
profileState: ZigProfileStateBuild
|
|
||||||
) : ZigDebugParametersBase<ZigProfileStateBuild>(driverConfiguration, toolchain, profileState), PreLaunchAware {
|
|
||||||
@Volatile
|
|
||||||
private lateinit var executableFile: File
|
|
||||||
|
|
||||||
override fun getInstaller(): Installer {
|
|
||||||
return ZigDebugEmitBinaryInstaller(profileState, toolchain, executableFile, profileState.configuration.exeArgs.argsSplit())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(ExecutionException::class)
|
|
||||||
override suspend fun preLaunch(listener: PreLaunchProcessListener) {
|
|
||||||
withProgressText("Building zig project") {
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
val commandLine = profileState.getCommandLine(toolchain, true)
|
|
||||||
if (listener.executeCommandLineWithHook(profileState.environment.project, commandLine))
|
|
||||||
return@withContext
|
|
||||||
val cfg = profileState.configuration
|
|
||||||
val workingDir = cfg.workingDirectory.path
|
|
||||||
val exe = profileState.configuration.exePath.path ?: run {
|
|
||||||
//Attempt autodetect, should work for trivial cases, and make most users happy, while advanced
|
|
||||||
// users can use manual executable paths.
|
|
||||||
if (workingDir == null) {
|
|
||||||
fail("debug.build.compile.failed.no-workdir")
|
|
||||||
}
|
|
||||||
val expectedOutputDir = workingDir.resolve(Path.of("zig-out", "bin"))
|
|
||||||
if (!expectedOutputDir.toFile().exists()) {
|
|
||||||
fail("debug.build.compile.failed.autodetect")
|
|
||||||
}
|
|
||||||
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
Files.list(expectedOutputDir).use { getExe(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!exe.toFile().exists())
|
|
||||||
fail("debug.build.compile.failed.no-file", exe)
|
|
||||||
else if (!exe.isExecutable())
|
|
||||||
fail("debug.build.compile.failed.non-exec-file", exe)
|
|
||||||
|
|
||||||
executableFile = exe.toFile()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(ExecutionException::class)
|
|
||||||
private fun getExe(files: Stream<Path>): Path {
|
|
||||||
var fileStream = files.filter { it.isRegularFile() }
|
|
||||||
if (SystemInfo.isWindows) {
|
|
||||||
fileStream = fileStream.filter { it.fileName.endsWith(".exe") }
|
|
||||||
} else {
|
|
||||||
fileStream = fileStream.filter { it.isExecutable() }
|
|
||||||
}
|
|
||||||
val executables = fileStream.toList()
|
|
||||||
return when(executables.size) {
|
|
||||||
0 -> fail("debug.base.compile.failed.no-exe")
|
|
||||||
1 -> executables[0]
|
|
||||||
else -> fail("debug.build.compile.failed.multiple-exe")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(ExecutionException::class)
|
|
||||||
private fun fail(@PropertyKey(resourceBundle = ZigDebugBundle.BUNDLE) messageKey: String, vararg params: Any): Nothing {
|
|
||||||
throw ExecutionException(ZigDebugBundle.message("debug.build.compile.failed.boilerplate", ZigDebugBundle.message(messageKey, params)))
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.runner.build
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersBase
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugRunnerBase
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigProfileState
|
|
||||||
import com.falsepattern.zigbrains.project.execution.build.ZigExecConfigBuild
|
|
||||||
import com.falsepattern.zigbrains.project.execution.build.ZigProfileStateBuild
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.local.LocalZigToolchain
|
|
||||||
import com.intellij.execution.configurations.RunProfile
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
|
|
||||||
|
|
||||||
class ZigDebugRunnerBuild: ZigDebugRunnerBase<ZigProfileStateBuild>() {
|
|
||||||
override fun getDebugParameters(
|
|
||||||
state: ZigProfileStateBuild,
|
|
||||||
debuggerDriver: DebuggerDriverConfiguration,
|
|
||||||
toolchain: ZigToolchain
|
|
||||||
): ZigDebugParametersBase<ZigProfileStateBuild> {
|
|
||||||
return ZigDebugParametersBuild(debuggerDriver, LocalZigToolchain.ensureLocal(toolchain), state)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun castProfileState(state: ZigProfileState<*>): ZigProfileStateBuild? {
|
|
||||||
return state as? ZigProfileStateBuild
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canRun(executorId: String, profile: RunProfile): Boolean {
|
|
||||||
return this.executorId == executorId && profile is ZigExecConfigBuild
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getRunnerId(): String {
|
|
||||||
return "ZigDebugRunnerBuild"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.runner.run
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugEmitBinaryInstaller
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersEmitBinaryBase
|
|
||||||
import com.falsepattern.zigbrains.project.execution.run.ZigProfileStateRun
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
|
||||||
import com.jetbrains.cidr.execution.Installer
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
|
|
||||||
|
|
||||||
class ZigDebugParametersRun(driverConfiguration: DebuggerDriverConfiguration, toolchain: ZigToolchain, profileState: ZigProfileStateRun) :
|
|
||||||
ZigDebugParametersEmitBinaryBase<ZigProfileStateRun>(driverConfiguration, toolchain, profileState) {
|
|
||||||
override fun getInstaller(): Installer {
|
|
||||||
return ZigDebugEmitBinaryInstaller(profileState, toolchain, executableFile, profileState.configuration.exeArgs.argsSplit())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.runner.run
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersBase
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugRunnerBase
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigProfileState
|
|
||||||
import com.falsepattern.zigbrains.project.execution.run.ZigExecConfigRun
|
|
||||||
import com.falsepattern.zigbrains.project.execution.run.ZigProfileStateRun
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.local.LocalZigToolchain
|
|
||||||
import com.intellij.execution.configurations.RunProfile
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
|
|
||||||
|
|
||||||
class ZigDebugRunnerRun: ZigDebugRunnerBase<ZigProfileStateRun>() {
|
|
||||||
override fun getDebugParameters(
|
|
||||||
state: ZigProfileStateRun,
|
|
||||||
debuggerDriver: DebuggerDriverConfiguration,
|
|
||||||
toolchain: ZigToolchain
|
|
||||||
): ZigDebugParametersBase<ZigProfileStateRun> {
|
|
||||||
return ZigDebugParametersRun(debuggerDriver, LocalZigToolchain.ensureLocal(toolchain), state)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun castProfileState(state: ZigProfileState<*>): ZigProfileStateRun? {
|
|
||||||
return state as? ZigProfileStateRun
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canRun(executorId: String, profile: RunProfile): Boolean {
|
|
||||||
return this.executorId == executorId && (profile is ZigExecConfigRun)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getRunnerId(): String {
|
|
||||||
return "ZigDebugRunnerRun"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.runner.test
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugEmitBinaryInstaller
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersEmitBinaryBase
|
|
||||||
import com.falsepattern.zigbrains.project.execution.test.ZigProfileStateTest
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
|
||||||
import com.jetbrains.cidr.execution.Installer
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
|
|
||||||
|
|
||||||
class ZigDebugParametersTest(driverConfiguration: DebuggerDriverConfiguration, toolchain: ZigToolchain, profileState: ZigProfileStateTest) :
|
|
||||||
ZigDebugParametersEmitBinaryBase<ZigProfileStateTest>(driverConfiguration, toolchain, profileState) {
|
|
||||||
override fun getInstaller(): Installer {
|
|
||||||
return ZigDebugEmitBinaryInstaller(profileState, toolchain, executableFile, listOf())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.runner.test
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersBase
|
|
||||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugRunnerBase
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigProfileState
|
|
||||||
import com.falsepattern.zigbrains.project.execution.test.ZigExecConfigTest
|
|
||||||
import com.falsepattern.zigbrains.project.execution.test.ZigProfileStateTest
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.local.LocalZigToolchain
|
|
||||||
import com.intellij.execution.configurations.RunProfile
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
|
|
||||||
|
|
||||||
class ZigDebugRunnerTest: ZigDebugRunnerBase<ZigProfileStateTest>() {
|
|
||||||
override fun getDebugParameters(
|
|
||||||
state: ZigProfileStateTest,
|
|
||||||
debuggerDriver: DebuggerDriverConfiguration,
|
|
||||||
toolchain: ZigToolchain
|
|
||||||
): ZigDebugParametersBase<ZigProfileStateTest> {
|
|
||||||
return ZigDebugParametersTest(debuggerDriver, LocalZigToolchain.ensureLocal(toolchain), state)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun castProfileState(state: ZigProfileState<*>): ZigProfileStateTest? {
|
|
||||||
return state as? ZigProfileStateTest
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canRun(executorId: String, profile: RunProfile): Boolean {
|
|
||||||
return this.executorId == executorId && profile is ZigExecConfigTest
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getRunnerId(): String {
|
|
||||||
return "ZigDebugRunnerTest"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.settings
|
|
||||||
|
|
||||||
enum class MSVCDownloadPermission {
|
|
||||||
AskMe,
|
|
||||||
Allow,
|
|
||||||
Deny
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.settings
|
|
||||||
|
|
||||||
import com.intellij.openapi.Disposable
|
|
||||||
import com.intellij.openapi.options.ConfigurableUi
|
|
||||||
import com.intellij.openapi.util.Disposer
|
|
||||||
import com.intellij.ui.dsl.builder.panel
|
|
||||||
import javax.swing.JComponent
|
|
||||||
|
|
||||||
class ZigDebuggerGeneralSettingsConfigurableUi: ConfigurableUi<ZigDebuggerSettings>, Disposable {
|
|
||||||
private val components = listOf<ZigDebuggerUiComponent>(ZigDebuggerToolchainConfigurableUi()).onEach { Disposer.register(this, it) }
|
|
||||||
|
|
||||||
override fun reset(settings: ZigDebuggerSettings) {
|
|
||||||
components.forEach { it.reset(settings) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isModified(settings: ZigDebuggerSettings): Boolean {
|
|
||||||
return components.any { it.isModified(settings) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun apply(settings: ZigDebuggerSettings) {
|
|
||||||
components.forEach { it.apply(settings) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getComponent(): JComponent {
|
|
||||||
return panel {
|
|
||||||
components.forEach { it.buildUi(this) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun dispose() {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.settings
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.ZigDebugBundle
|
|
||||||
import com.falsepattern.zigbrains.debugger.toolchain.DebuggerKind
|
|
||||||
import com.intellij.openapi.options.Configurable
|
|
||||||
import com.intellij.openapi.options.SimpleConfigurable
|
|
||||||
import com.intellij.util.xmlb.XmlSerializerUtil
|
|
||||||
import com.intellij.xdebugger.settings.DebuggerSettingsCategory
|
|
||||||
import com.intellij.xdebugger.settings.XDebuggerSettings
|
|
||||||
import java.util.function.Supplier
|
|
||||||
|
|
||||||
class ZigDebuggerSettings: XDebuggerSettings<ZigDebuggerSettings>("Zig") {
|
|
||||||
var debuggerKind = DebuggerKind.default
|
|
||||||
|
|
||||||
var downloadAutomatically = false
|
|
||||||
var useClion = true
|
|
||||||
var msvcConsent = MSVCDownloadPermission.AskMe
|
|
||||||
|
|
||||||
override fun getState(): ZigDebuggerSettings {
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun loadState(p0: ZigDebuggerSettings) {
|
|
||||||
XmlSerializerUtil.copyBean(p0, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createConfigurables(category: DebuggerSettingsCategory): Collection<Configurable> {
|
|
||||||
val configurable = when(category) {
|
|
||||||
DebuggerSettingsCategory.GENERAL -> createGeneralSettingsConfigurable()
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
return configurable?.let { listOf(configurable) } ?: emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createGeneralSettingsConfigurable(): Configurable {
|
|
||||||
return SimpleConfigurable.create(
|
|
||||||
GENERAL_SETTINGS_ID,
|
|
||||||
ZigDebugBundle.message("settings.debugger.title"),
|
|
||||||
ZigDebuggerGeneralSettingsConfigurableUi::class.java,
|
|
||||||
Supplier {
|
|
||||||
instance
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val instance: ZigDebuggerSettings get() = getInstance(ZigDebuggerSettings::class.java)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private const val GENERAL_SETTINGS_ID = "Debugger.Zig.General"
|
|
|
@ -1,154 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.settings
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.ZigDebugBundle
|
|
||||||
import com.falsepattern.zigbrains.debugger.toolchain.DebuggerAvailability
|
|
||||||
import com.falsepattern.zigbrains.debugger.toolchain.DebuggerKind
|
|
||||||
import com.falsepattern.zigbrains.debugger.toolchain.ZigDebuggerToolchainService
|
|
||||||
import com.falsepattern.zigbrains.debugger.toolchain.zigDebuggerToolchainService
|
|
||||||
import com.falsepattern.zigbrains.shared.coroutine.launchWithEDT
|
|
||||||
import com.falsepattern.zigbrains.shared.coroutine.runModalOrBlocking
|
|
||||||
import com.falsepattern.zigbrains.shared.zigCoroutineScope
|
|
||||||
import com.intellij.ide.plugins.PluginManager
|
|
||||||
import com.intellij.openapi.application.ModalityState
|
|
||||||
import com.intellij.openapi.extensions.PluginId
|
|
||||||
import com.intellij.openapi.observable.util.whenItemSelected
|
|
||||||
import com.intellij.openapi.ui.ComboBox
|
|
||||||
import com.intellij.openapi.util.SystemInfo
|
|
||||||
import com.intellij.platform.ide.progress.ModalTaskOwner
|
|
||||||
import com.intellij.platform.ide.progress.TaskCancellation
|
|
||||||
import com.intellij.platform.ide.progress.withModalProgress
|
|
||||||
import com.intellij.ui.components.JBCheckBox
|
|
||||||
import com.intellij.ui.dsl.builder.DEFAULT_COMMENT_WIDTH
|
|
||||||
import com.intellij.ui.dsl.builder.Panel
|
|
||||||
import com.intellij.util.concurrency.annotations.RequiresEdt
|
|
||||||
import javax.swing.ComboBoxModel
|
|
||||||
import javax.swing.DefaultComboBoxModel
|
|
||||||
import javax.swing.JEditorPane
|
|
||||||
|
|
||||||
class ZigDebuggerToolchainConfigurableUi : ZigDebuggerUiComponent {
|
|
||||||
private val debuggerKindComboBox = ComboBox(
|
|
||||||
runModalOrBlocking({ ModalTaskOwner.guess() }, { "ZigDebuggerToolchainConfigurableUi" }) {
|
|
||||||
createDebuggerKindComboBoxModel()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
private val downloadAutomaticallyCheckBox = JBCheckBox(
|
|
||||||
ZigDebugBundle.message("settings.debugger.toolchain.download.debugger.automatically.checkbox"),
|
|
||||||
ZigDebuggerSettings.instance.downloadAutomatically
|
|
||||||
)
|
|
||||||
|
|
||||||
private val useClion = JBCheckBox(
|
|
||||||
ZigDebugBundle.message("settings.debugger.toolchain.use.clion.toolchains"),
|
|
||||||
ZigDebuggerSettings.instance.useClion
|
|
||||||
)
|
|
||||||
|
|
||||||
private var comment: JEditorPane? = null
|
|
||||||
|
|
||||||
private val currentDebuggerKind get() = debuggerKindComboBox.item
|
|
||||||
|
|
||||||
override fun reset(settings: ZigDebuggerSettings) {
|
|
||||||
debuggerKindComboBox.item = settings.debuggerKind
|
|
||||||
downloadAutomaticallyCheckBox.isSelected = settings.downloadAutomatically
|
|
||||||
useClion.isSelected = settings.useClion
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isModified(settings: ZigDebuggerSettings): Boolean {
|
|
||||||
return settings.debuggerKind != debuggerKindComboBox.item ||
|
|
||||||
settings.downloadAutomatically != downloadAutomaticallyCheckBox.isSelected ||
|
|
||||||
settings.useClion != useClion.isSelected
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun apply(settings: ZigDebuggerSettings) {
|
|
||||||
settings.debuggerKind = debuggerKindComboBox.item
|
|
||||||
settings.downloadAutomatically = downloadAutomaticallyCheckBox.isSelected
|
|
||||||
settings.useClion = useClion.isSelected
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun buildUi(panel: Panel): Unit = with(panel) {
|
|
||||||
row(ZigDebugBundle.message("settings.debugger.toolchain.debugger.label")) {
|
|
||||||
comment = cell(debuggerKindComboBox)
|
|
||||||
.comment("", DEFAULT_COMMENT_WIDTH) {
|
|
||||||
zigCoroutineScope.launchWithEDT(ModalityState.defaultModalityState()) {
|
|
||||||
withModalProgress(ModalTaskOwner.component(debuggerKindComboBox), "Downloading debugger", TaskCancellation.cancellable()) {
|
|
||||||
downloadDebugger()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.applyToComponent {
|
|
||||||
whenItemSelected(null) {
|
|
||||||
zigCoroutineScope.launchWithEDT(ModalityState.defaultModalityState()) {
|
|
||||||
this@ZigDebuggerToolchainConfigurableUi.update()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.comment
|
|
||||||
}
|
|
||||||
row {
|
|
||||||
cell(downloadAutomaticallyCheckBox)
|
|
||||||
}
|
|
||||||
if (PluginManager.isPluginInstalled(PluginId.getId("com.intellij.modules.clion")) && !SystemInfo.isWindows) {
|
|
||||||
row {
|
|
||||||
cell(useClion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
zigCoroutineScope.launchWithEDT(ModalityState.defaultModalityState()) {
|
|
||||||
update()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun dispose() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresEdt
|
|
||||||
private suspend fun downloadDebugger() {
|
|
||||||
val result = zigDebuggerToolchainService.downloadDebugger(null, currentDebuggerKind)
|
|
||||||
if (result is ZigDebuggerToolchainService.DownloadResult.Ok) {
|
|
||||||
update()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresEdt
|
|
||||||
private suspend fun update() {
|
|
||||||
val availability = zigDebuggerToolchainService.debuggerAvailability(currentDebuggerKind)
|
|
||||||
val text = when (availability) {
|
|
||||||
is DebuggerAvailability.NeedToDownload -> ZigDebugBundle.message("settings.debugger.toolchain.download.comment")
|
|
||||||
is DebuggerAvailability.NeedToUpdate -> ZigDebugBundle.message("settings.debugger.toolchain.update.comment")
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
comment?.let {
|
|
||||||
it.text = text
|
|
||||||
it.isVisible = text != null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private suspend fun createDebuggerKindComboBoxModel(): ComboBoxModel<DebuggerKind> {
|
|
||||||
val toolchainService = zigDebuggerToolchainService
|
|
||||||
val availableKinds = DebuggerKind.entries.filter { toolchainService.debuggerAvailability(it) !is DebuggerAvailability.Unavailable }
|
|
||||||
return DefaultComboBoxModel(availableKinds.toTypedArray()).also { it.selectedItem = ZigDebuggerSettings.instance.debuggerKind }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.settings
|
|
||||||
|
|
||||||
import com.intellij.openapi.Disposable
|
|
||||||
import com.intellij.openapi.options.ConfigurableUi
|
|
||||||
import com.intellij.ui.dsl.builder.Panel
|
|
||||||
import com.intellij.ui.dsl.builder.panel
|
|
||||||
import javax.swing.JComponent
|
|
||||||
|
|
||||||
interface ZigDebuggerUiComponent: ConfigurableUi<ZigDebuggerSettings>, Disposable {
|
|
||||||
fun buildUi(panel: Panel)
|
|
||||||
|
|
||||||
override fun getComponent(): JComponent {
|
|
||||||
return panel {
|
|
||||||
buildUi(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.toolchain
|
|
||||||
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
sealed class DebuggerAvailability<out T> {
|
|
||||||
data object Unavailable: DebuggerAvailability<Nothing>()
|
|
||||||
data object NeedToDownload: DebuggerAvailability<Nothing>()
|
|
||||||
data object NeedToUpdate: DebuggerAvailability<Nothing>()
|
|
||||||
data object Bundled: DebuggerAvailability<Nothing>()
|
|
||||||
data class Binaries<T> (val binaries: T): DebuggerAvailability<T>()
|
|
||||||
}
|
|
||||||
|
|
||||||
data class LLDBBinaries(val frameworkFile: Path, val frontendFile: Path)
|
|
||||||
data class GDBBinaries(val gdbFile: Path)
|
|
||||||
data class MSVCBinaries(val msvcFile: Path)
|
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.toolchain
|
|
||||||
|
|
||||||
import com.intellij.openapi.util.SystemInfo
|
|
||||||
|
|
||||||
enum class DebuggerKind {
|
|
||||||
LLDB,
|
|
||||||
GDB,
|
|
||||||
MSVC;
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val default get() = if (SystemInfo.isWindows) MSVC else LLDB
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,126 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.toolchain
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.ZigDebugBundle
|
|
||||||
import com.falsepattern.zigbrains.debugger.settings.MSVCDownloadPermission
|
|
||||||
import com.falsepattern.zigbrains.debugger.settings.ZigDebuggerSettings
|
|
||||||
import com.falsepattern.zigbrains.debugger.toolchain.ZigDebuggerToolchainService.Companion.downloadPath
|
|
||||||
import com.falsepattern.zigbrains.shared.coroutine.withCurrentEDTModalityContext
|
|
||||||
import com.intellij.notification.Notification
|
|
||||||
import com.intellij.notification.NotificationType
|
|
||||||
import com.intellij.openapi.progress.coroutineToIndicator
|
|
||||||
import com.intellij.openapi.ui.DialogBuilder
|
|
||||||
import com.intellij.platform.util.progress.withProgressText
|
|
||||||
import com.intellij.ui.components.JBLabel
|
|
||||||
import com.intellij.ui.components.JBPanel
|
|
||||||
import com.intellij.util.download.DownloadableFileService
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
|
||||||
import kotlinx.coroutines.sync.withLock
|
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
|
||||||
import java.io.IOException
|
|
||||||
import java.util.*
|
|
||||||
import javax.swing.BoxLayout
|
|
||||||
|
|
||||||
private val mutex = Mutex()
|
|
||||||
private var cache: Properties? = null
|
|
||||||
|
|
||||||
suspend fun msvcMetadata(): Properties {
|
|
||||||
cache?.let { return it }
|
|
||||||
mutex.withLock {
|
|
||||||
cache?.let { return it }
|
|
||||||
val settings = ZigDebuggerSettings.instance
|
|
||||||
var permission = settings.msvcConsent
|
|
||||||
if (permission == MSVCDownloadPermission.AskMe) {
|
|
||||||
val allowDownload = withCurrentEDTModalityContext {
|
|
||||||
val dialog = DialogBuilder()
|
|
||||||
dialog.setTitle(ZigDebugBundle.message("msvc.consent.title"))
|
|
||||||
dialog.addCancelAction().setText(ZigDebugBundle.message("msvc.consent.deny"))
|
|
||||||
dialog.addOkAction().setText(ZigDebugBundle.message("msvc.consent.allow"))
|
|
||||||
val centerPanel = JBPanel<JBPanel<*>>()
|
|
||||||
centerPanel.setLayout(BoxLayout(centerPanel, BoxLayout.Y_AXIS))
|
|
||||||
val lines = ZigDebugBundle.message("msvc.consent.body").split('\n')
|
|
||||||
for (line in lines) {
|
|
||||||
centerPanel.add(JBLabel(line))
|
|
||||||
}
|
|
||||||
dialog.centerPanel(centerPanel)
|
|
||||||
dialog.showAndGet()
|
|
||||||
}
|
|
||||||
permission = if (allowDownload) MSVCDownloadPermission.Allow else MSVCDownloadPermission.Deny
|
|
||||||
settings.msvcConsent = permission
|
|
||||||
}
|
|
||||||
val data = if (permission == MSVCDownloadPermission.Allow) {
|
|
||||||
withTimeoutOrNull(3000L) {
|
|
||||||
downloadMSVCProps()
|
|
||||||
} ?: run {
|
|
||||||
Notification(
|
|
||||||
"zigbrains",
|
|
||||||
ZigDebugBundle.message("notification.title.debugger"),
|
|
||||||
ZigDebugBundle.message("notification.content.debugger.metadata.downloading.failed"),
|
|
||||||
NotificationType.ERROR
|
|
||||||
).notify(null)
|
|
||||||
fetchBuiltinMSVCProps()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fetchBuiltinMSVCProps()
|
|
||||||
}
|
|
||||||
cache = data
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun downloadMSVCProps(): Properties {
|
|
||||||
return withProgressText("Downloading debugger metadata") {
|
|
||||||
val service = DownloadableFileService.getInstance()
|
|
||||||
val desc = service.createFileDescription("https://falsepattern.com/zigbrains/msvc.properties", "msvc.properties")
|
|
||||||
val downloader = service.createDownloader(listOf(desc), "Debugger metadata downloading")
|
|
||||||
val downloadDirectory = downloadPath().toFile()
|
|
||||||
val prop = Properties()
|
|
||||||
val downloadResults = coroutineToIndicator {
|
|
||||||
downloader.download(downloadDirectory)
|
|
||||||
}
|
|
||||||
for (result in downloadResults) {
|
|
||||||
if (result.second.defaultFileName == "msvc.properties") {
|
|
||||||
result.first.reader().use { prop.load(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return@withProgressText prop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun fetchBuiltinMSVCProps(): Properties {
|
|
||||||
val prop = Properties()
|
|
||||||
try {
|
|
||||||
val resource = ZigDebuggerToolchainService::class.java.getResourceAsStream("/msvc.properties") ?: throw IOException("null")
|
|
||||||
resource.reader().use { prop.load(it) }
|
|
||||||
} catch (ex: IOException) {
|
|
||||||
ex.printStackTrace()
|
|
||||||
Notification(
|
|
||||||
"zigbrains",
|
|
||||||
ZigDebugBundle.message("notification.title.debugger"),
|
|
||||||
ZigDebugBundle.message("notification.content.debugger.metadata.fallback.parse.failed"),
|
|
||||||
NotificationType.ERROR
|
|
||||||
).notify(null)
|
|
||||||
}
|
|
||||||
return prop
|
|
||||||
}
|
|
|
@ -1,350 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.toolchain
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.ZigDebugBundle
|
|
||||||
import com.falsepattern.zigbrains.shared.Unarchiver
|
|
||||||
import com.intellij.notification.Notification
|
|
||||||
import com.intellij.notification.NotificationType
|
|
||||||
import com.intellij.openapi.application.PathManager
|
|
||||||
import com.intellij.openapi.components.Service
|
|
||||||
import com.intellij.openapi.components.service
|
|
||||||
import com.intellij.openapi.diagnostic.logger
|
|
||||||
import com.intellij.openapi.progress.coroutineToIndicator
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.ui.DialogBuilder
|
|
||||||
import com.intellij.openapi.util.SystemInfo
|
|
||||||
import com.intellij.openapi.util.io.toNioPathOrNull
|
|
||||||
import com.intellij.platform.util.progress.reportSequentialProgress
|
|
||||||
import com.intellij.ui.BrowserHyperlinkListener
|
|
||||||
import com.intellij.ui.HyperlinkLabel
|
|
||||||
import com.intellij.ui.components.JBPanel
|
|
||||||
import com.intellij.util.application
|
|
||||||
import com.intellij.util.concurrency.annotations.RequiresEdt
|
|
||||||
import com.intellij.util.download.DownloadableFileService
|
|
||||||
import com.intellij.util.system.CpuArch
|
|
||||||
import com.intellij.util.system.OS
|
|
||||||
import com.jetbrains.cidr.execution.debugger.CidrDebuggerPathManager
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.bin.UrlProvider
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.lldb.LLDBDriverConfiguration
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import java.io.IOException
|
|
||||||
import java.net.URL
|
|
||||||
import java.nio.file.Path
|
|
||||||
import java.util.*
|
|
||||||
import kotlin.io.path.name
|
|
||||||
|
|
||||||
@Service
|
|
||||||
class ZigDebuggerToolchainService {
|
|
||||||
suspend fun debuggerAvailability(kind: DebuggerKind): DebuggerAvailability<*> {
|
|
||||||
return when(kind) {
|
|
||||||
DebuggerKind.LLDB -> lldbAvailability()
|
|
||||||
DebuggerKind.GDB -> gdbAvailability()
|
|
||||||
DebuggerKind.MSVC -> msvcAvailability()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun lldbAvailability(): DebuggerAvailability<LLDBBinaries> {
|
|
||||||
if (LLDBDriverConfiguration.hasBundledLLDB()) return DebuggerAvailability.Bundled
|
|
||||||
|
|
||||||
val (frameworkPath, frontendPath) = when {
|
|
||||||
SystemInfo.isMac -> "LLDB.framework" to "LLDBFrontend"
|
|
||||||
SystemInfo.isUnix -> "lib/liblldb.so" to "bin/LLDBFrontend"
|
|
||||||
// SystemInfo.isWindows -> "bin/liblldb.dll" to "bin/LLDBFrontend.exe"
|
|
||||||
else -> return DebuggerAvailability.Unavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
val lldbPath = lldbPath()
|
|
||||||
val frameworkFile = lldbPath.resolve(frameworkPath)
|
|
||||||
val frontendFile = lldbPath.resolve(frontendPath)
|
|
||||||
if (!frameworkFile.toFile().exists() || !frontendFile.toFile().exists()) return DebuggerAvailability.NeedToDownload
|
|
||||||
|
|
||||||
val versions = loadDebuggerVersions(DebuggerKind.LLDB)
|
|
||||||
val (lldbFrameworkUrl, lldbFrontendUrl) = lldbUrls() ?: return DebuggerAvailability.Unavailable
|
|
||||||
|
|
||||||
val lldbFrameworkVersion = fileNameWithoutExtension(lldbFrameworkUrl.toString())
|
|
||||||
val lldbFrontendVersion = fileNameWithoutExtension(lldbFrontendUrl.toString())
|
|
||||||
|
|
||||||
if (versions[LLDB_FRAMEWORK_PROPERTY_NAME] != lldbFrameworkVersion ||
|
|
||||||
versions[LLDB_FRONTEND_PROPERTY_NAME] != lldbFrontendVersion) return DebuggerAvailability.NeedToUpdate
|
|
||||||
|
|
||||||
return DebuggerAvailability.Binaries(LLDBBinaries(frameworkFile, frontendFile))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun gdbAvailability(): DebuggerAvailability<GDBBinaries> {
|
|
||||||
if (SystemInfo.isMac) return DebuggerAvailability.Unavailable
|
|
||||||
if (CidrDebuggerPathManager.getBundledGDBBinary().exists()) return DebuggerAvailability.Bundled
|
|
||||||
|
|
||||||
val gdbBinaryPath = when {
|
|
||||||
SystemInfo.isUnix -> "bin/gdb"
|
|
||||||
// SystemInfo.isWindows -> "bin/gdb.exe"
|
|
||||||
else -> return DebuggerAvailability.Unavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
val gdbFile = gdbPath().resolve(gdbBinaryPath)
|
|
||||||
if (!gdbFile.toFile().exists()) return DebuggerAvailability.NeedToDownload
|
|
||||||
|
|
||||||
val versions = loadDebuggerVersions(DebuggerKind.GDB)
|
|
||||||
val gdbUrl = gdbUrl() ?: return DebuggerAvailability.Unavailable
|
|
||||||
|
|
||||||
val gdbVersion = fileNameWithoutExtension(gdbUrl.toString())
|
|
||||||
|
|
||||||
if (versions[GDB_PROPERTY_NAME] != gdbVersion) return DebuggerAvailability.NeedToUpdate
|
|
||||||
|
|
||||||
return DebuggerAvailability.Binaries(GDBBinaries(gdbFile))
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun msvcAvailability(): DebuggerAvailability<MSVCBinaries> {
|
|
||||||
if (!SystemInfo.isWindows) return DebuggerAvailability.Unavailable
|
|
||||||
|
|
||||||
val msvcBinaryPath = "vsdbg.exe"
|
|
||||||
|
|
||||||
val msvcFile = msvcPath().resolve(msvcBinaryPath)
|
|
||||||
if (!msvcFile.toFile().exists()) return DebuggerAvailability.NeedToDownload
|
|
||||||
|
|
||||||
val msvcUrl = msvcUrl() ?: return DebuggerAvailability.Binaries(MSVCBinaries(msvcFile))
|
|
||||||
|
|
||||||
val versions = loadDebuggerVersions(DebuggerKind.MSVC)
|
|
||||||
|
|
||||||
if (versions[MSVC_PROPERTY_NAME] != msvcUrl.version) return DebuggerAvailability.NeedToUpdate
|
|
||||||
|
|
||||||
return DebuggerAvailability.Binaries(MSVCBinaries(msvcFile))
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresEdt
|
|
||||||
private suspend fun doDownloadDebugger(debuggerKind: DebuggerKind): DownloadResult {
|
|
||||||
val baseDir = debuggerKind.basePath()
|
|
||||||
val downloadableBinaries = when(debuggerKind) {
|
|
||||||
DebuggerKind.LLDB -> {
|
|
||||||
val (lldbFrameworkUrl, lldbFrontendUrl) = lldbUrls()?.run { first.toString() to second.toString() } ?: return DownloadResult.NoUrls
|
|
||||||
listOf(
|
|
||||||
DownloadableDebuggerBinary(lldbFrameworkUrl, LLDB_FRAMEWORK_PROPERTY_NAME, fileNameWithoutExtension(lldbFrameworkUrl)),
|
|
||||||
DownloadableDebuggerBinary(lldbFrontendUrl, LLDB_FRONTEND_PROPERTY_NAME, fileNameWithoutExtension(lldbFrontendUrl))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
DebuggerKind.GDB -> {
|
|
||||||
val gdbUrl = gdbUrl()?.run { toString() } ?: return DownloadResult.NoUrls
|
|
||||||
listOf(DownloadableDebuggerBinary(gdbUrl, GDB_PROPERTY_NAME, fileNameWithoutExtension(gdbUrl)))
|
|
||||||
}
|
|
||||||
DebuggerKind.MSVC -> {
|
|
||||||
val msvcUrl = msvcUrl() ?: return DownloadResult.NoUrls
|
|
||||||
|
|
||||||
val dialog = DialogBuilder()
|
|
||||||
dialog.setTitle(msvcUrl.dialogTitle)
|
|
||||||
dialog.addCancelAction().setText("Reject")
|
|
||||||
dialog.addOkAction().setText("Accept")
|
|
||||||
val centerPanel = JBPanel<JBPanel<*>>()
|
|
||||||
val hyperlink = HyperlinkLabel()
|
|
||||||
hyperlink.setTextWithHyperlink(msvcUrl.dialogBody)
|
|
||||||
hyperlink.setHyperlinkTarget(msvcUrl.dialogLink)
|
|
||||||
hyperlink.addHyperlinkListener(BrowserHyperlinkListener())
|
|
||||||
centerPanel.add(hyperlink)
|
|
||||||
dialog.centerPanel(centerPanel)
|
|
||||||
if (!dialog.showAndGet()) return DownloadResult.NoUrls
|
|
||||||
|
|
||||||
listOf(DownloadableDebuggerBinary(msvcUrl.url, MSVC_PROPERTY_NAME, msvcUrl.version, "extension/debugAdapters/vsdbg/bin"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
downloadAndUnArchive(baseDir, downloadableBinaries)
|
|
||||||
}
|
|
||||||
return DownloadResult.Ok(baseDir)
|
|
||||||
} catch (e: IOException) {
|
|
||||||
//TODO logging
|
|
||||||
e.printStackTrace()
|
|
||||||
return DownloadResult.Failed(e.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresEdt
|
|
||||||
suspend fun downloadDebugger(project: Project? = null, debuggerKind: DebuggerKind): DownloadResult {
|
|
||||||
val result = doDownloadDebugger(debuggerKind)
|
|
||||||
|
|
||||||
when(result) {
|
|
||||||
is DownloadResult.Ok -> {
|
|
||||||
Notification(
|
|
||||||
"zigbrains",
|
|
||||||
ZigDebugBundle.message("notification.title.debugger"),
|
|
||||||
ZigDebugBundle.message("notification.content.debugger.successfully.downloaded"),
|
|
||||||
NotificationType.INFORMATION
|
|
||||||
).notify(project)
|
|
||||||
}
|
|
||||||
is DownloadResult.Failed -> {
|
|
||||||
Notification(
|
|
||||||
"zigbrains",
|
|
||||||
ZigDebugBundle.message("notification.title.debugger"),
|
|
||||||
ZigDebugBundle.message("notification.content.debugger.downloading.failed"),
|
|
||||||
NotificationType.ERROR
|
|
||||||
).notify(project)
|
|
||||||
}
|
|
||||||
else -> Unit
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(IOException::class)
|
|
||||||
@RequiresEdt
|
|
||||||
private suspend fun downloadAndUnArchive(baseDir: Path, binariesToDownload: List<DownloadableDebuggerBinary>) {
|
|
||||||
reportSequentialProgress { reporter ->
|
|
||||||
val service = DownloadableFileService.getInstance()
|
|
||||||
|
|
||||||
val downloadDir = baseDir.toFile()
|
|
||||||
downloadDir.deleteRecursively()
|
|
||||||
|
|
||||||
val descriptions = binariesToDownload.map {
|
|
||||||
service.createFileDescription(it.url, fileName(it.url))
|
|
||||||
}
|
|
||||||
|
|
||||||
val downloader = service.createDownloader(descriptions, "Debugger downloading")
|
|
||||||
val downloadDirectory = downloadPath().toFile()
|
|
||||||
val downloadResults = reporter.sizedStep(100) {
|
|
||||||
coroutineToIndicator {
|
|
||||||
downloader.download(downloadDirectory)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val versions = Properties()
|
|
||||||
for (result in downloadResults) {
|
|
||||||
val downloadUrl = result.second.downloadUrl
|
|
||||||
val binaryToDownload = binariesToDownload.first { it.url == downloadUrl }
|
|
||||||
val propertyName = binaryToDownload.propertyName
|
|
||||||
val archiveFile = result.first
|
|
||||||
reporter.indeterminateStep {
|
|
||||||
coroutineToIndicator {
|
|
||||||
Unarchiver.unarchive(archiveFile.toPath(), baseDir, binaryToDownload.prefix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
archiveFile.delete()
|
|
||||||
versions[propertyName] = binaryToDownload.version
|
|
||||||
}
|
|
||||||
|
|
||||||
saveVersionsFile(baseDir, versions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun lldbUrls(): Pair<URL, URL>? {
|
|
||||||
val lldb = UrlProvider.lldb(OS.CURRENT, CpuArch.CURRENT) ?: return null
|
|
||||||
val lldbFrontend = UrlProvider.lldbFrontend(OS.CURRENT, CpuArch.CURRENT) ?: return null
|
|
||||||
return lldb to lldbFrontend
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun gdbUrl(): URL? = UrlProvider.gdb(OS.CURRENT, CpuArch.CURRENT)
|
|
||||||
|
|
||||||
private suspend fun msvcUrl(): MSVCUrl? {
|
|
||||||
val dlKey = when(CpuArch.CURRENT) {
|
|
||||||
CpuArch.X86 -> "downloadX86"
|
|
||||||
CpuArch.X86_64 -> "downloadX86_64"
|
|
||||||
CpuArch.ARM64 -> "downloadARM64"
|
|
||||||
else -> return null
|
|
||||||
}
|
|
||||||
|
|
||||||
val props = msvcMetadata()
|
|
||||||
val version = props.getProperty("version") ?: return null
|
|
||||||
val url = props.getProperty(dlKey) ?: return null
|
|
||||||
return MSVCUrl(url, version, props.getProperty("dialogTitle")!!, props.getProperty("dialogBody")!!, props.getProperty("dialogLink")!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
private data class MSVCUrl(
|
|
||||||
val url: String,
|
|
||||||
val version: String,
|
|
||||||
val dialogTitle: String,
|
|
||||||
val dialogBody: String,
|
|
||||||
val dialogLink: String
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun loadDebuggerVersions(kind: DebuggerKind): Properties = loadVersions(kind.basePath())
|
|
||||||
|
|
||||||
private fun saveVersionsFile(basePath: Path, versions: Properties) {
|
|
||||||
val file = basePath.resolve(DEBUGGER_VERSIONS).toFile()
|
|
||||||
try {
|
|
||||||
versions.store(file.bufferedWriter(), "")
|
|
||||||
} catch (e: IOException) {
|
|
||||||
LOG.warn("Failed to save `${basePath.name}/${file.name}`", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadVersions(basePath: Path): Properties {
|
|
||||||
val versions = Properties()
|
|
||||||
val versionsFile = basePath.resolve(DEBUGGER_VERSIONS).toFile()
|
|
||||||
|
|
||||||
if (versionsFile.exists()) {
|
|
||||||
try {
|
|
||||||
versionsFile.bufferedReader().use { versions.load(it) }
|
|
||||||
} catch (e: IOException) {
|
|
||||||
LOG.warn("Failed to load `${basePath.name}/${versionsFile.name}`", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return versions
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun DebuggerKind.basePath(): Path {
|
|
||||||
return when(this) {
|
|
||||||
DebuggerKind.LLDB -> lldbPath()
|
|
||||||
DebuggerKind.GDB -> gdbPath()
|
|
||||||
DebuggerKind.MSVC -> msvcPath()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val LOG = logger<ZigDebuggerToolchainService>()
|
|
||||||
|
|
||||||
private const val DEBUGGER_VERSIONS: String = "versions.properties"
|
|
||||||
|
|
||||||
private const val LLDB_FRONTEND_PROPERTY_NAME = "lldbFrontend"
|
|
||||||
private const val LLDB_FRAMEWORK_PROPERTY_NAME = "lldbFramework"
|
|
||||||
private const val GDB_PROPERTY_NAME = "gdb"
|
|
||||||
private const val MSVC_PROPERTY_NAME = "msvc"
|
|
||||||
|
|
||||||
fun downloadPath() = tempPluginDir
|
|
||||||
private fun lldbPath() = pluginDir.resolve("lldb")
|
|
||||||
private fun gdbPath() = pluginDir.resolve("gdb")
|
|
||||||
private fun msvcPath() = pluginDir.resolve("msvc")
|
|
||||||
|
|
||||||
private val pluginDir get() = PathManager.getSystemDir().resolve("zigbrains")
|
|
||||||
|
|
||||||
private val tempPluginDir get(): Path = PathManager.getTempPath().toNioPathOrNull()!!.resolve("zigbrains")
|
|
||||||
|
|
||||||
private fun fileNameWithoutExtension(url: String): String {
|
|
||||||
return url.substringAfterLast("/").removeSuffix(".zip").removeSuffix(".tar.gz")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun fileName(url: String): String {
|
|
||||||
return url.substringAfterLast("/")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class DownloadResult {
|
|
||||||
class Ok(val baseDir: Path): DownloadResult()
|
|
||||||
data object NoUrls: DownloadResult()
|
|
||||||
class Failed(val message: String?): DownloadResult()
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmRecord
|
|
||||||
private data class DownloadableDebuggerBinary(val url: String, val propertyName: String, val version: String, val prefix: String? = null)
|
|
||||||
}
|
|
||||||
|
|
||||||
val zigDebuggerToolchainService get() = application.service<ZigDebuggerToolchainService>()
|
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.win
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.dap.DAPDebuggerDriverConfiguration
|
|
||||||
import com.intellij.execution.configurations.GeneralCommandLine
|
|
||||||
import com.jetbrains.cidr.ArchitectureType
|
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriver
|
|
||||||
import org.eclipse.lsp4j.debug.InitializeRequestArguments
|
|
||||||
import java.nio.file.Path
|
|
||||||
import kotlin.io.path.pathString
|
|
||||||
|
|
||||||
abstract class MSVCDriverConfiguration: DAPDebuggerDriverConfiguration() {
|
|
||||||
protected abstract val debuggerExecutable: Path
|
|
||||||
|
|
||||||
override fun createDriver(handler: DebuggerDriver.Handler, arch: ArchitectureType): DebuggerDriver {
|
|
||||||
return WinDAPDriver(handler).also { it.initialize(this) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createDriverCommandLine(driver: DebuggerDriver, arch: ArchitectureType): GeneralCommandLine {
|
|
||||||
val path = debuggerExecutable
|
|
||||||
val cli = GeneralCommandLine()
|
|
||||||
cli.withExePath(path.pathString)
|
|
||||||
cli.addParameters("--interpreter=vscode", "--extconfigdir=%USERPROFILE%\\.cppvsdbg\\extensions")
|
|
||||||
cli.withWorkingDirectory(path.parent)
|
|
||||||
return cli
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun customizeInitializeArguments(initArgs: InitializeRequestArguments) {
|
|
||||||
initArgs.pathFormat = "path"
|
|
||||||
initArgs.adapterID = "cppvsdbg"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,129 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.debugger.win
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.debugger.dap.DAPDriver
|
|
||||||
import com.falsepattern.zigbrains.shared.zigCoroutineScope
|
|
||||||
import com.intellij.util.system.CpuArch
|
|
||||||
import com.jetbrains.cidr.ArchitectureType
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.async
|
|
||||||
import kotlinx.coroutines.future.asCompletableFuture
|
|
||||||
import kotlinx.coroutines.sync.Semaphore
|
|
||||||
import org.eclipse.lsp4j.debug.Capabilities
|
|
||||||
import org.eclipse.lsp4j.debug.OutputEventArguments
|
|
||||||
import org.eclipse.lsp4j.debug.services.IDebugProtocolServer
|
|
||||||
import org.eclipse.lsp4j.debug.util.ToStringBuilder
|
|
||||||
import org.eclipse.lsp4j.jsonrpc.MessageConsumer
|
|
||||||
import org.eclipse.lsp4j.jsonrpc.debug.messages.DebugResponseMessage
|
|
||||||
import org.eclipse.lsp4j.jsonrpc.messages.Message
|
|
||||||
import org.eclipse.lsp4j.jsonrpc.services.JsonRequest
|
|
||||||
import java.io.InputStream
|
|
||||||
import java.security.MessageDigest
|
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.CompletableFuture
|
|
||||||
import java.util.zip.Inflater
|
|
||||||
|
|
||||||
class WinDAPDriver(handler: Handler) : DAPDriver<IDebugProtocolServer, WinDAPDriver.WinDAPDebuggerClient>(handler) {
|
|
||||||
private val handshakeFinished = Semaphore(1, 1)
|
|
||||||
|
|
||||||
override fun createDebuggerClient(): WinDAPDebuggerClient {
|
|
||||||
return WinDAPDebuggerClient()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getServerInterface(): Class<IDebugProtocolServer> {
|
|
||||||
return IDebugProtocolServer::class.java
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun wrapMessageConsumer(mc: MessageConsumer): MessageConsumer {
|
|
||||||
return object: MessageConsumer {
|
|
||||||
private var verifyHandshake = true
|
|
||||||
override fun consume(message: Message) {
|
|
||||||
if (verifyHandshake && message is DebugResponseMessage && message.method == "handshake") {
|
|
||||||
verifyHandshake = false
|
|
||||||
message.setResponseId(1)
|
|
||||||
}
|
|
||||||
mc.consume(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun postInitialize(capabilities: Capabilities) {
|
|
||||||
handshakeFinished.acquire()
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class WinDAPDebuggerClient: DAPDriver<IDebugProtocolServer, WinDAPDebuggerClient>.DAPDebuggerClient() {
|
|
||||||
override fun output(args: OutputEventArguments) {
|
|
||||||
if ("telemetry" == args.category)
|
|
||||||
return
|
|
||||||
|
|
||||||
super.output(args)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonRequest
|
|
||||||
fun handshake(handshake: HandshakeRequest): CompletableFuture<HandshakeResponse> {
|
|
||||||
return zigCoroutineScope.async(Dispatchers.IO) {
|
|
||||||
handshakeSuspend(handshake)
|
|
||||||
}.asCompletableFuture()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handshakeSuspend(handshake: HandshakeRequest): HandshakeResponse {
|
|
||||||
val hasher = MessageDigest.getInstance("SHA-256")
|
|
||||||
hasher.update(handshake.value.encodeToByteArray())
|
|
||||||
val inflater = Inflater(true)
|
|
||||||
val coconut = DAPDebuggerClient::class.java.getResourceAsStream("/coconut.jpg")?.use(InputStream::readAllBytes) ?: throw RuntimeException("No coconut")
|
|
||||||
inflater.setInput(coconut, coconut.size - 80, 77)
|
|
||||||
inflater.finished()
|
|
||||||
val b = ByteArray(1)
|
|
||||||
while (inflater.inflate(b) > 0)
|
|
||||||
hasher.update(b)
|
|
||||||
val result = HandshakeResponse(String(coconut, coconut.size - 3, 3) + Base64.getEncoder().encodeToString(hasher.digest()))
|
|
||||||
handshakeFinished.release()
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getArchitecture(): String {
|
|
||||||
return ArchitectureType.forVmCpuArch(CpuArch.CURRENT).id
|
|
||||||
}
|
|
||||||
|
|
||||||
data class HandshakeRequest(var value: String) {
|
|
||||||
constructor() : this("")
|
|
||||||
override fun toString(): String {
|
|
||||||
val b = ToStringBuilder(this)
|
|
||||||
b.add("value", value)
|
|
||||||
return b.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class HandshakeResponse(var signature: String) {
|
|
||||||
constructor() : this("")
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
val b = ToStringBuilder(this)
|
|
||||||
b.add("signature", this.signature)
|
|
||||||
return b.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
<idea-plugin package="com.falsepattern.zigbrains.cidr">
|
|
||||||
<depends>com.intellij.cidr.base</depends>
|
|
||||||
<extensions defaultExtensionNs="cidr.project">
|
|
||||||
<workspaceProvider
|
|
||||||
implementation="com.falsepattern.zigbrains.cidr.ZigWorkspaceProvider"
|
|
||||||
/>
|
|
||||||
</extensions>
|
|
||||||
</idea-plugin>
|
|
|
@ -1,10 +0,0 @@
|
||||||
<idea-plugin package="com.falsepattern.zigbrains.clion">
|
|
||||||
<depends>com.intellij.clion</depends>
|
|
||||||
<extensions defaultExtensionNs="com.falsepattern.zigbrains">
|
|
||||||
<debuggerDriverProvider
|
|
||||||
id="CLionProvider"
|
|
||||||
implementation="com.falsepattern.zigbrains.clion.ZigClionDebuggerDriverConfigurationProvider"
|
|
||||||
order="before DefaultProvider"
|
|
||||||
/>
|
|
||||||
</extensions>
|
|
||||||
</idea-plugin>
|
|
|
@ -1,60 +0,0 @@
|
||||||
<idea-plugin package="com.falsepattern.zigbrains.debugger">
|
|
||||||
<depends>com.intellij.modules.cidr.debugger</depends>
|
|
||||||
|
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
|
||||||
<configurationType
|
|
||||||
implementation="com.falsepattern.zigbrains.debugger.execution.binary.ZigConfigTypeBinary"
|
|
||||||
/>
|
|
||||||
<programRunner
|
|
||||||
id="ZigDebugRunnerRun"
|
|
||||||
implementation="com.falsepattern.zigbrains.debugger.runner.run.ZigDebugRunnerRun"
|
|
||||||
/>
|
|
||||||
<programRunner
|
|
||||||
id="ZigDebugRunnerTest"
|
|
||||||
implementation="com.falsepattern.zigbrains.debugger.runner.test.ZigDebugRunnerTest"
|
|
||||||
/>
|
|
||||||
<programRunner
|
|
||||||
id="ZigDebugRunnerBuild"
|
|
||||||
implementation="com.falsepattern.zigbrains.debugger.runner.build.ZigDebugRunnerBuild"
|
|
||||||
/>
|
|
||||||
<programRunner
|
|
||||||
id="ZigDebugRunnerBinary"
|
|
||||||
implementation="com.falsepattern.zigbrains.debugger.runner.binary.ZigDebugRunnerBinary"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<xdebugger.settings
|
|
||||||
implementation="com.falsepattern.zigbrains.debugger.settings.ZigDebuggerSettings"
|
|
||||||
/>
|
|
||||||
</extensions>
|
|
||||||
|
|
||||||
<extensions defaultExtensionNs="com.falsepattern.zigbrains">
|
|
||||||
<featureProvider
|
|
||||||
implementation="com.falsepattern.zigbrains.debugger.DebuggerFeatures"
|
|
||||||
/>
|
|
||||||
<debuggerDriverProvider
|
|
||||||
id="DefaultProvider"
|
|
||||||
implementation="com.falsepattern.zigbrains.debugger.ZigDefaultDebuggerDriverConfigurationProvider"
|
|
||||||
order="last"
|
|
||||||
/>
|
|
||||||
</extensions>
|
|
||||||
|
|
||||||
<extensions defaultExtensionNs="cidr.debugger">
|
|
||||||
<languageSupport
|
|
||||||
language="Zig"
|
|
||||||
implementationClass="com.falsepattern.zigbrains.debugger.ZigDebuggerLanguageSupport"
|
|
||||||
/>
|
|
||||||
<editorsExtension
|
|
||||||
language="Zig"
|
|
||||||
implementationClass="com.falsepattern.zigbrains.debugger.ZigDebuggerEditorsExtension"
|
|
||||||
/>
|
|
||||||
<lineBreakpointFileTypesProvider
|
|
||||||
implementation="com.falsepattern.zigbrains.debugger.ZigLineBreakpointFileTypesProvider"
|
|
||||||
/>
|
|
||||||
<localVariablesFilterHandler
|
|
||||||
implementation="com.falsepattern.zigbrains.debugger.ZigLocalVariablesFilterHandler"
|
|
||||||
/>
|
|
||||||
</extensions>
|
|
||||||
|
|
||||||
<extensionPoints>
|
|
||||||
</extensionPoints>
|
|
||||||
</idea-plugin>
|
|
|
@ -1,36 +0,0 @@
|
||||||
notification.title.debugger=Debugger
|
|
||||||
notification.content.debugger.successfully.downloaded=Debugger successfully downloaded
|
|
||||||
notification.content.debugger.downloading.failed=Debugger downloading failed
|
|
||||||
notification.content.debugger.metadata.downloading.failed=Debugger metadata downloading failed, switching to fallback
|
|
||||||
notification.content.debugger.metadata.fallback.parse.failed=Debugger fallback metadata parse failed
|
|
||||||
settings.debugger.toolchain.download.debugger.automatically.checkbox=Download and update the debugger automatically
|
|
||||||
settings.debugger.title=Zig
|
|
||||||
settings.debugger.toolchain.debugger.label=Debugger:
|
|
||||||
settings.debugger.toolchain.download.comment=Need to be <a>downloaded</a>
|
|
||||||
settings.debugger.toolchain.update.comment=Need to be <a>updated</a>
|
|
||||||
settings.debugger.toolchain.use.clion.toolchains=Use Clion toolchains instead
|
|
||||||
debugger.run.unavailable=Unable to Run Debugger
|
|
||||||
debugger.run.unavailable.reason.download=Debugger is not downloaded yet
|
|
||||||
debugger.run.unavailable.reason.download.button=Download
|
|
||||||
debugger.run.unavailable.reason.update=Debugger is outdated
|
|
||||||
debugger.run.unavailable.reason.update.button=Update
|
|
||||||
debug.build.compile.failed.boilerplate={0}\nPlease edit this intellij build configuration and specify the path of the executable created by "zig build" directly!
|
|
||||||
debug.base.compile.failed.generic=Failed to compile executable with command: {0}
|
|
||||||
debug.base.compile.failed.no-exe=Failed to find compiled binary
|
|
||||||
debug.build.compile.failed.multiple-exe=Multiple compiled binaries found
|
|
||||||
debug.build.compile.failed.no-workdir=Cannot find working directory to run debugged executable
|
|
||||||
debug.build.compile.failed.autodetect=Could not auto-detect default executable output directory "zig-out/bin"
|
|
||||||
debug.build.compile.failed.no-file=File `{0}` does not exist
|
|
||||||
debug.build.compile.failed.non-exec-file=File `{0}` is not executable
|
|
||||||
debug.build.compile.failed.generic=Failed to build project
|
|
||||||
exec.type.binary.label=Zig-compiled native executable
|
|
||||||
exec.option.label.binary.exe-path=Executable program path (not the zig compiler)
|
|
||||||
exec.option.label.binary.args=Command line arguments
|
|
||||||
exception.missing-exe-path=Missing executable path
|
|
||||||
configuration.binary.name=Native Application (Zig)
|
|
||||||
configuration.binary.suggested-name=Executable
|
|
||||||
configuration.binary.description=Binary executable compiled from zig code (useful for debugging on Windows)
|
|
||||||
msvc.consent.title=Network Request Consent
|
|
||||||
msvc.consent.deny=Use Bundled
|
|
||||||
msvc.consent.allow=Download
|
|
||||||
msvc.consent.body=Debugging on Windows requires downloading extra metadata from the internet.\nThe bundled fallback metadata will be used if the request is denied.
|
|
|
@ -1,108 +0,0 @@
|
||||||
import org.jetbrains.grammarkit.tasks.GenerateLexerTask
|
|
||||||
import org.jetbrains.grammarkit.tasks.GenerateParserTask
|
|
||||||
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
id("org.jetbrains.grammarkit")
|
|
||||||
kotlin("plugin.serialization")
|
|
||||||
}
|
|
||||||
|
|
||||||
val ideaCommunityVersion: String by project
|
|
||||||
val useInstaller = property("useInstaller").toString().toBoolean()
|
|
||||||
val serializationVersion: String by project
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
intellijPlatform {
|
|
||||||
create(IntelliJPlatformType.IntellijIdeaCommunity, ideaCommunityVersion, useInstaller = useInstaller)
|
|
||||||
}
|
|
||||||
compileOnly("org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:$serializationVersion") {
|
|
||||||
isTransitive = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//region grammars
|
|
||||||
run {
|
|
||||||
val grammarGenRoot = layout.buildDirectory.dir("generated/sources/grammarkit")
|
|
||||||
val rootPackagePath = "com/falsepattern/zigbrains"
|
|
||||||
val grammarSources = layout.projectDirectory.dir("src/main/grammar")
|
|
||||||
|
|
||||||
val parserDir = grammarGenRoot.map {it.dir("zig/parser")}
|
|
||||||
val lexerDir = grammarGenRoot.map {it.dir("zig/lexer")}
|
|
||||||
val lexerStringDir = grammarGenRoot.map {it.dir("zig/lexerstring")}
|
|
||||||
val zonParserDir = grammarGenRoot.map {it.dir("zon/parser")}
|
|
||||||
val zonLexerDir = grammarGenRoot.map {it.dir("zon/lexer")}
|
|
||||||
|
|
||||||
val grammarGenDirs = listOf(parserDir, lexerDir, lexerStringDir, zonParserDir, zonLexerDir)
|
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
main {
|
|
||||||
java {
|
|
||||||
grammarGenDirs.forEach { srcDir(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
idea {
|
|
||||||
module {
|
|
||||||
grammarGenDirs.forEach {
|
|
||||||
val file = it.get().asFile
|
|
||||||
sourceDirs.add(file)
|
|
||||||
generatedSourceDirs.add(file)
|
|
||||||
}
|
|
||||||
sourceDirs.add(grammarSources.asFile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks {
|
|
||||||
// region grammarkit
|
|
||||||
generateLexer {
|
|
||||||
purgeOldFiles = true
|
|
||||||
sourceFile = grammarSources.file("Zig.flex")
|
|
||||||
targetOutputDir = lexerDir.map { it.dir("$rootPackagePath/zig/lexer") }
|
|
||||||
}
|
|
||||||
|
|
||||||
register<GenerateLexerTask>("generateLexerString") {
|
|
||||||
purgeOldFiles = true
|
|
||||||
sourceFile = grammarSources.file("ZigString.flex")
|
|
||||||
targetOutputDir = lexerStringDir.map { it.dir("$rootPackagePath/zig/lexerstring") }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
generateParser {
|
|
||||||
purgeOldFiles = true
|
|
||||||
sourceFile = grammarSources.file("Zig.bnf")
|
|
||||||
targetRootOutputDir = parserDir
|
|
||||||
pathToParser = "$rootPackagePath/zig/parser/ZigParser.java"
|
|
||||||
pathToPsiRoot = "$rootPackagePath/zig/psi"
|
|
||||||
}
|
|
||||||
|
|
||||||
register<GenerateLexerTask>("generateZonLexer") {
|
|
||||||
purgeOldFiles = true
|
|
||||||
sourceFile = grammarSources.file("Zon.flex")
|
|
||||||
targetOutputDir = zonLexerDir.map { it.dir("$rootPackagePath/zon/lexer") }
|
|
||||||
}
|
|
||||||
|
|
||||||
register<GenerateParserTask>("generateZonParser") {
|
|
||||||
purgeOldFiles = true
|
|
||||||
sourceFile = grammarSources.file("Zon.bnf")
|
|
||||||
targetRootOutputDir = zonParserDir
|
|
||||||
pathToParser = "$rootPackagePath/zon/parser/ZonParser.java"
|
|
||||||
pathToPsiRoot = "$rootPackagePath/zon/psi"
|
|
||||||
}
|
|
||||||
|
|
||||||
register<DefaultTask>("generateGrammars") {
|
|
||||||
group = "grammarkit"
|
|
||||||
dependsOn("generateLexer", "generateLexerString", "generateParser")
|
|
||||||
dependsOn("generateZonLexer", "generateZonParser")
|
|
||||||
}
|
|
||||||
|
|
||||||
compileJava {
|
|
||||||
dependsOn("generateGrammars")
|
|
||||||
}
|
|
||||||
|
|
||||||
compileKotlin {
|
|
||||||
dependsOn("generateGrammars")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//endregion grammars
|
|
|
@ -1,84 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package com.falsepattern.zigbrains.zig.lexerstring;
|
|
||||||
|
|
||||||
import com.intellij.lexer.FlexLexer;
|
|
||||||
import com.intellij.psi.tree.IElementType;
|
|
||||||
|
|
||||||
import static com.intellij.psi.TokenType.WHITE_SPACE;
|
|
||||||
import static com.intellij.psi.TokenType.BAD_CHARACTER;
|
|
||||||
import static com.falsepattern.zigbrains.zig.psi.ZigTypes.*;
|
|
||||||
import static com.intellij.psi.StringEscapesTokenTypes.*;
|
|
||||||
|
|
||||||
%%
|
|
||||||
|
|
||||||
%public
|
|
||||||
%class ZigLexerString
|
|
||||||
%implements FlexLexer
|
|
||||||
%function advance
|
|
||||||
%type IElementType
|
|
||||||
|
|
||||||
hex=[0-9a-fA-F]
|
|
||||||
|
|
||||||
char_escape_unicode= "\\x" {hex} {hex} | "\\u{" {hex}+ "}"
|
|
||||||
char_escape_unicode_invalid= "\\x" .? .? | "\\u" ("{" [^}]* "}"?)?
|
|
||||||
|
|
||||||
char_escape_single_valid= "\\" [nr\\t'\"]
|
|
||||||
char_escape_single_invalid= "\\" [^nr\\t'\"]
|
|
||||||
|
|
||||||
%state STR
|
|
||||||
%state CHAR
|
|
||||||
%state CHAR_END
|
|
||||||
%state CHAR_FINISH
|
|
||||||
%%
|
|
||||||
|
|
||||||
|
|
||||||
<YYINITIAL> {
|
|
||||||
"\"" { yybegin(STR); return STRING_LITERAL_SINGLE; }
|
|
||||||
"'" { yybegin(CHAR); return CHAR_LITERAL; }
|
|
||||||
[^] { return STRING_LITERAL_SINGLE; }
|
|
||||||
}
|
|
||||||
|
|
||||||
<STR> {
|
|
||||||
{char_escape_unicode} { return VALID_STRING_ESCAPE_TOKEN; }
|
|
||||||
{char_escape_unicode_invalid} { return INVALID_UNICODE_ESCAPE_TOKEN; }
|
|
||||||
{char_escape_single_valid} { return VALID_STRING_ESCAPE_TOKEN; }
|
|
||||||
{char_escape_single_invalid} { return INVALID_CHARACTER_ESCAPE_TOKEN; }
|
|
||||||
[^] { return STRING_LITERAL_SINGLE; }
|
|
||||||
}
|
|
||||||
|
|
||||||
<CHAR> {
|
|
||||||
{char_escape_unicode} { yybegin(CHAR_END); return VALID_STRING_ESCAPE_TOKEN; }
|
|
||||||
{char_escape_unicode_invalid} { yybegin(CHAR_END); return INVALID_UNICODE_ESCAPE_TOKEN; }
|
|
||||||
{char_escape_single_valid} { yybegin(CHAR_END); return VALID_STRING_ESCAPE_TOKEN; }
|
|
||||||
{char_escape_single_invalid} { yybegin(CHAR_END); return INVALID_CHARACTER_ESCAPE_TOKEN; }
|
|
||||||
[^] { yybegin(CHAR_END); return CHAR_LITERAL; }
|
|
||||||
}
|
|
||||||
|
|
||||||
<CHAR_END> {
|
|
||||||
"'" { yybegin(CHAR_FINISH); return CHAR_LITERAL; }
|
|
||||||
[^] { return BAD_CHARACTER; }
|
|
||||||
}
|
|
||||||
|
|
||||||
<CHAR_FINISH> {
|
|
||||||
[^] { return BAD_CHARACTER; }
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
{
|
|
||||||
parserClass="com.falsepattern.zigbrains.zon.parser.ZonParser"
|
|
||||||
|
|
||||||
extends="com.intellij.extapi.psi.ASTWrapperPsiElement"
|
|
||||||
|
|
||||||
psiClassPrefix="Zon"
|
|
||||||
psiImplClassSuffix="Impl"
|
|
||||||
psiPackage="com.falsepattern.zigbrains.zon.psi"
|
|
||||||
psiImplPackage="com.falsepattern.zigbrains.zon.psi.impl"
|
|
||||||
|
|
||||||
elementTypeHolderClass="com.falsepattern.zigbrains.zon.psi.ZonTypes"
|
|
||||||
elementTypeClass="com.falsepattern.zigbrains.zon.parser.ZonElementType"
|
|
||||||
tokenTypeClass="com.falsepattern.zigbrains.zon.parser.ZonTokenType"
|
|
||||||
tokens=[
|
|
||||||
LINE_COMMENT='comment'
|
|
||||||
DOT='.'
|
|
||||||
EQUAL='='
|
|
||||||
LBRACE='{'
|
|
||||||
RBRACE='}'
|
|
||||||
COMMA=','
|
|
||||||
KEYWORD_FALSE='false'
|
|
||||||
KEYWORD_TRUE='true'
|
|
||||||
KEYWORD_NULL='null'
|
|
||||||
NUM_NAN='nan'
|
|
||||||
NUM_INF='inf'
|
|
||||||
CHAR_LITERAL='char literal'
|
|
||||||
STRING_LITERAL_SINGLE='string literal'
|
|
||||||
STRING_LITERAL_MULTI='multiline string literal'
|
|
||||||
FLOAT='float'
|
|
||||||
INTEGER='integer'
|
|
||||||
IDENTIFIER='identifier'
|
|
||||||
BAD_SQUOT='unterminated quote'
|
|
||||||
BAD_DQUOT='unterminated double quote'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
Root ::= Expr
|
|
||||||
|
|
||||||
Expr
|
|
||||||
::= CHAR_LITERAL
|
|
||||||
| StringLiteral
|
|
||||||
| DOT IDENTIFIER
|
|
||||||
| DOT InitList
|
|
||||||
| Bool
|
|
||||||
| Number
|
|
||||||
| KEYWORD_NULL
|
|
||||||
|
|
||||||
|
|
||||||
InitList
|
|
||||||
::= LBRACE ZB_InitList_Body RBRACE {pin=1}
|
|
||||||
|
|
||||||
private ZB_InitList_Body
|
|
||||||
::= FieldInit (COMMA ZB_InitList_FieldInit)* COMMA?
|
|
||||||
| Expr (COMMA ZB_InitList_Expr)* COMMA?
|
|
||||||
| ()
|
|
||||||
|
|
||||||
private ZB_InitList_FieldInit ::= FieldInit {recoverWhile="ZB_InitList_Recover"}
|
|
||||||
private ZB_InitList_Expr ::= Expr {recoverWhile="ZB_InitList_Recover"}
|
|
||||||
|
|
||||||
private ZB_InitList_Recover ::= !(COMMA | RBRACE)
|
|
||||||
|
|
||||||
FieldInit ::= DOT IDENTIFIER EQUAL Expr
|
|
||||||
|
|
||||||
Bool ::= KEYWORD_TRUE | KEYWORD_FALSE
|
|
||||||
|
|
||||||
Number ::= FLOAT | INTEGER | NUM_NAN | NUM_INF
|
|
||||||
|
|
||||||
StringLiteral ::= STRING_LITERAL_SINGLE | STRING_LITERAL_MULTI
|
|
|
@ -1,159 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package com.falsepattern.zigbrains.zon.lexer;
|
|
||||||
|
|
||||||
import com.intellij.lexer.FlexLexer;
|
|
||||||
import com.intellij.psi.tree.IElementType;
|
|
||||||
|
|
||||||
import static com.intellij.psi.TokenType.WHITE_SPACE;
|
|
||||||
import static com.intellij.psi.TokenType.BAD_CHARACTER;
|
|
||||||
import static com.falsepattern.zigbrains.zon.psi.ZonTypes.*;
|
|
||||||
|
|
||||||
%%
|
|
||||||
|
|
||||||
%class ZonFlexLexer
|
|
||||||
%implements FlexLexer
|
|
||||||
%function advance
|
|
||||||
%type IElementType
|
|
||||||
%unicode
|
|
||||||
|
|
||||||
WHITE_SPACE=\s+
|
|
||||||
|
|
||||||
// visual studio parity
|
|
||||||
LF=\r\n?|[\n\u0085\u2028\u2029]
|
|
||||||
|
|
||||||
bin=[01]
|
|
||||||
bin_="_"? {bin}
|
|
||||||
oct=[0-7]
|
|
||||||
oct_="_"? {oct}
|
|
||||||
hex=[0-9a-fA-F]
|
|
||||||
hex_="_"? {hex}
|
|
||||||
dec=[0-9]
|
|
||||||
dec_="_"? {dec}
|
|
||||||
|
|
||||||
bin_int={bin} {bin_}*
|
|
||||||
oct_int={oct} {oct_}*
|
|
||||||
dec_int={dec} {dec_}*
|
|
||||||
hex_int={hex} {hex_}*
|
|
||||||
|
|
||||||
char_char= \\ .
|
|
||||||
| [^\'\r\n\u0085\u2028\u2029]
|
|
||||||
|
|
||||||
string_char= \\ .
|
|
||||||
| [^\"\r\n\u0085\u2028\u2029]
|
|
||||||
|
|
||||||
nl_wrap={LF} (\s|{LF})*
|
|
||||||
all_no_nl=[^\r\n\u0085\u2028\u2029]+
|
|
||||||
|
|
||||||
|
|
||||||
FLOAT= "0x" {hex_int} "." {hex_int} ([pP] [-+]? {dec_int})?
|
|
||||||
| {dec_int} "." {dec_int} ([eE] [-+]? {dec_int})?
|
|
||||||
| "0x" {hex_int} [pP] [-+]? {dec_int}
|
|
||||||
| {dec_int} [eE] [-+]? {dec_int}
|
|
||||||
|
|
||||||
INTEGER= "0b" {bin_int}
|
|
||||||
| "0o" {oct_int}
|
|
||||||
| "0x" {hex_int}
|
|
||||||
| {dec_int}
|
|
||||||
|
|
||||||
IDENTIFIER_PLAIN=[A-Za-z_][A-Za-z0-9_]*
|
|
||||||
|
|
||||||
%state STR_LIT
|
|
||||||
%state STR_MULT_LINE
|
|
||||||
%state CHAR_LIT
|
|
||||||
|
|
||||||
%state ID_QUOT
|
|
||||||
%state UNT_SQUOT
|
|
||||||
%state UNT_DQUOT
|
|
||||||
|
|
||||||
%state CMT_LINE
|
|
||||||
%%
|
|
||||||
|
|
||||||
//Comments
|
|
||||||
|
|
||||||
<YYINITIAL> "//" { yybegin(CMT_LINE); }
|
|
||||||
<CMT_LINE> {all_no_nl} { }
|
|
||||||
<CMT_LINE> {nl_wrap} "//" { }
|
|
||||||
<CMT_LINE> \R { yybegin(YYINITIAL); return LINE_COMMENT; }
|
|
||||||
<CMT_LINE> <<EOF>> { yybegin(YYINITIAL); return LINE_COMMENT; }
|
|
||||||
|
|
||||||
//Symbols
|
|
||||||
|
|
||||||
<YYINITIAL> "." { return DOT; }
|
|
||||||
<YYINITIAL> "=" { return EQUAL; }
|
|
||||||
<YYINITIAL> "{" { return LBRACE; }
|
|
||||||
<YYINITIAL> "}" { return RBRACE; }
|
|
||||||
<YYINITIAL> "," { return COMMA; }
|
|
||||||
|
|
||||||
//Keywords
|
|
||||||
|
|
||||||
<YYINITIAL> "false" { return KEYWORD_FALSE; }
|
|
||||||
<YYINITIAL> "true" { return KEYWORD_TRUE; }
|
|
||||||
<YYINITIAL> "null" { return KEYWORD_NULL; }
|
|
||||||
<YYINITIAL> "nan" { return NUM_NAN; }
|
|
||||||
<YYINITIAL> "inf" { return NUM_INF; }
|
|
||||||
|
|
||||||
//Strings
|
|
||||||
|
|
||||||
<YYINITIAL> "'" { yybegin(CHAR_LIT); }
|
|
||||||
<CHAR_LIT> {char_char}*"'" { yybegin(YYINITIAL); return CHAR_LITERAL; }
|
|
||||||
<CHAR_LIT> <<EOF>> { yybegin(YYINITIAL); return BAD_SQUOT; }
|
|
||||||
<CHAR_LIT> [^] { yypushback(1); yybegin(UNT_SQUOT); }
|
|
||||||
|
|
||||||
<YYINITIAL> "\"" { yybegin(STR_LIT); }
|
|
||||||
<STR_LIT> {string_char}*"\"" { yybegin(YYINITIAL); return STRING_LITERAL_SINGLE; }
|
|
||||||
<STR_LIT> <<EOF>> { yybegin(YYINITIAL); return BAD_DQUOT; }
|
|
||||||
<STR_LIT> [^] { yypushback(1); yybegin(UNT_DQUOT); }
|
|
||||||
|
|
||||||
<YYINITIAL> "\\\\" { yybegin(STR_MULT_LINE); }
|
|
||||||
<STR_MULT_LINE> {all_no_nl} { }
|
|
||||||
<STR_MULT_LINE> {nl_wrap} "\\\\" { }
|
|
||||||
<STR_MULT_LINE> {LF} { yybegin(YYINITIAL); return STRING_LITERAL_MULTI; }
|
|
||||||
<STR_MULT_LINE> <<EOF>> { yybegin(YYINITIAL); return STRING_LITERAL_MULTI; }
|
|
||||||
|
|
||||||
//Numbers
|
|
||||||
|
|
||||||
<YYINITIAL> {FLOAT} { return FLOAT; }
|
|
||||||
<YYINITIAL> {INTEGER} { return INTEGER; }
|
|
||||||
|
|
||||||
//Identifiers
|
|
||||||
|
|
||||||
<YYINITIAL> {IDENTIFIER_PLAIN} { return IDENTIFIER; }
|
|
||||||
<YYINITIAL> "@\"" { yybegin(ID_QUOT); }
|
|
||||||
<ID_QUOT> {string_char}*"\"" { yybegin(YYINITIAL); return IDENTIFIER; }
|
|
||||||
<ID_QUOT> <<EOF>> { yybegin(YYINITIAL); return BAD_DQUOT; }
|
|
||||||
<ID_QUOT> [^] { yypushback(1); yybegin(UNT_DQUOT); }
|
|
||||||
|
|
||||||
//Error handling
|
|
||||||
|
|
||||||
<UNT_SQUOT> <<EOF>> { yybegin(YYINITIAL); return BAD_SQUOT; }
|
|
||||||
<UNT_SQUOT> {LF} { yybegin(YYINITIAL); return BAD_SQUOT; }
|
|
||||||
<UNT_SQUOT> {all_no_nl} { }
|
|
||||||
<UNT_DQUOT> <<EOF>> { yybegin(YYINITIAL); return BAD_DQUOT; }
|
|
||||||
<UNT_DQUOT> {LF} { yybegin(YYINITIAL); return BAD_DQUOT; }
|
|
||||||
<UNT_DQUOT> {all_no_nl} { }
|
|
||||||
|
|
||||||
//Misc
|
|
||||||
|
|
||||||
<YYINITIAL> {WHITE_SPACE} { return WHITE_SPACE; }
|
|
||||||
|
|
||||||
[^] { return BAD_CHARACTER; }
|
|
|
@ -1,34 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains
|
|
||||||
|
|
||||||
import com.intellij.openapi.util.IconLoader
|
|
||||||
import org.jetbrains.annotations.NonNls
|
|
||||||
|
|
||||||
@NonNls
|
|
||||||
object Icons {
|
|
||||||
@JvmField
|
|
||||||
val Zig = IconLoader.getIcon("/icons/zig.svg", Icons::class.java)
|
|
||||||
@JvmField
|
|
||||||
val Zon = IconLoader.getIcon("/icons/zon.svg", Icons::class.java)
|
|
||||||
}
|
|
|
@ -1,107 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains
|
|
||||||
|
|
||||||
import com.intellij.ide.BrowserUtil
|
|
||||||
import com.intellij.ide.plugins.PluginManager
|
|
||||||
import com.intellij.notification.Notification
|
|
||||||
import com.intellij.notification.NotificationAction
|
|
||||||
import com.intellij.notification.NotificationType
|
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
|
||||||
import com.intellij.openapi.extensions.PluginId
|
|
||||||
import com.intellij.openapi.options.Configurable
|
|
||||||
import com.intellij.openapi.options.ShowSettingsUtil
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.startup.ProjectActivity
|
|
||||||
import java.lang.reflect.Constructor
|
|
||||||
import java.lang.reflect.Method
|
|
||||||
|
|
||||||
class ZBStartup: ProjectActivity {
|
|
||||||
var firstInit = true
|
|
||||||
override suspend fun execute(project: Project) {
|
|
||||||
if (firstInit) {
|
|
||||||
firstInit = false
|
|
||||||
if (!PluginManager.isPluginInstalled(PluginId.getId("com.intellij.modules.cidr.debugger")) &&
|
|
||||||
PluginManager.isPluginInstalled(PluginId.getId("com.intellij.modules.nativeDebug-plugin-capable"))) {
|
|
||||||
val notif = Notification(
|
|
||||||
"zigbrains",
|
|
||||||
ZigBrainsBundle.message("notification.title.native-debug"),
|
|
||||||
ZigBrainsBundle.message("notification.content.native-debug"),
|
|
||||||
NotificationType.INFORMATION
|
|
||||||
)
|
|
||||||
if (JBInternalPluginManagerConfigurable.successful) {
|
|
||||||
notif.addAction(object: NotificationAction(ZigBrainsBundle.message("notification.content.native-debug.market")) {
|
|
||||||
override fun actionPerformed(e: AnActionEvent, notification: Notification) {
|
|
||||||
val configurable = JBInternalPluginManagerConfigurable()
|
|
||||||
ShowSettingsUtil.getInstance().editConfigurable(null as Project?, configurable.instance) {
|
|
||||||
configurable.openMarketplaceTab("/vendor:\"JetBrains s.r.o.\" /tag:Debugging \"Native Debugging Support\"")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
notif.addAction(object: NotificationAction(ZigBrainsBundle.message("notification.content.native-debug.browser")) {
|
|
||||||
override fun actionPerformed(e: AnActionEvent, notification: Notification) {
|
|
||||||
BrowserUtil.browse("https://plugins.jetbrains.com/plugin/12775-native-debugging-support")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
notif.notify(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//JetBrains Internal API, but we need to access it, so access it reflectively (hopefully safe enough to pass verifier)
|
|
||||||
private class JBInternalPluginManagerConfigurable {
|
|
||||||
init {
|
|
||||||
if (!successful) {
|
|
||||||
throw IllegalStateException()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val instance = constructor.newInstance() as Configurable
|
|
||||||
|
|
||||||
fun openMarketplaceTab(option: String) {
|
|
||||||
openMarketplaceTab.invoke(instance, option)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private lateinit var constructor: Constructor<*>
|
|
||||||
private lateinit var openMarketplaceTab: Method
|
|
||||||
val successful: Boolean
|
|
||||||
|
|
||||||
init {
|
|
||||||
lateinit var constructor: Constructor<*>
|
|
||||||
lateinit var openMarketplaceTab: Method
|
|
||||||
val successful = try {
|
|
||||||
val theClass = Class.forName("com_intellij_ide_plugins_PluginManagerConfigurable".replace('_', '.'))
|
|
||||||
constructor = theClass.getDeclaredConstructor().apply { isAccessible = true }
|
|
||||||
openMarketplaceTab = theClass.getDeclaredMethod("openMarketplaceTab", String::class.java).apply { isAccessible = true }
|
|
||||||
true
|
|
||||||
} catch (_: Throwable) { false }
|
|
||||||
if (successful) {
|
|
||||||
this.constructor = constructor
|
|
||||||
this.openMarketplaceTab = openMarketplaceTab
|
|
||||||
}
|
|
||||||
this.successful = successful
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains
|
|
||||||
|
|
||||||
import com.intellij.DynamicBundle
|
|
||||||
import org.jetbrains.annotations.Nls
|
|
||||||
import org.jetbrains.annotations.NonNls
|
|
||||||
import org.jetbrains.annotations.PropertyKey
|
|
||||||
import java.util.function.Supplier
|
|
||||||
|
|
||||||
@NonNls
|
|
||||||
private const val BUNDLE = "zigbrains.Bundle"
|
|
||||||
|
|
||||||
internal object ZigBrainsBundle {
|
|
||||||
private val INSTANCE = DynamicBundle(ZigBrainsBundle::class.java, BUNDLE)
|
|
||||||
|
|
||||||
fun message(
|
|
||||||
key: @PropertyKey(resourceBundle = BUNDLE) String,
|
|
||||||
vararg params: Any
|
|
||||||
): @Nls String {
|
|
||||||
return INSTANCE.getMessage(key, *params)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun lazyMessage(
|
|
||||||
key: @PropertyKey(resourceBundle = BUNDLE) String,
|
|
||||||
vararg params: Any
|
|
||||||
): Supplier<@Nls String> {
|
|
||||||
return INSTANCE.getLazyMessage(key, *params)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.direnv
|
|
||||||
|
|
||||||
@JvmRecord
|
|
||||||
data class DirenvOutput(val output: String, val error: Boolean)
|
|
|
@ -1,162 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.direnv
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
|
||||||
import com.intellij.execution.configurations.GeneralCommandLine
|
|
||||||
import com.intellij.execution.configurations.PathEnvironmentVariableUtil
|
|
||||||
import com.intellij.ide.impl.isTrusted
|
|
||||||
import com.intellij.notification.Notification
|
|
||||||
import com.intellij.notification.NotificationType
|
|
||||||
import com.intellij.notification.Notifications
|
|
||||||
import com.intellij.openapi.components.*
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.project.guessProjectDir
|
|
||||||
import com.intellij.openapi.util.Key
|
|
||||||
import com.intellij.openapi.util.UserDataHolder
|
|
||||||
import com.intellij.openapi.vfs.toNioPathOrNull
|
|
||||||
import com.intellij.platform.util.progress.withProgressText
|
|
||||||
import com.intellij.util.io.awaitExit
|
|
||||||
import com.intellij.util.xmlb.annotations.Attribute
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
|
||||||
import kotlinx.coroutines.sync.withLock
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.serialization.json.Json
|
|
||||||
import java.nio.file.Path
|
|
||||||
import kotlin.io.path.isRegularFile
|
|
||||||
|
|
||||||
@Service(Service.Level.PROJECT)
|
|
||||||
@State(
|
|
||||||
name = "Direnv",
|
|
||||||
storages = [Storage("zigbrains.xml")]
|
|
||||||
)
|
|
||||||
class DirenvService(val project: Project): SerializablePersistentStateComponent<DirenvService.State>(State()), IDirenvService {
|
|
||||||
private val mutex = Mutex()
|
|
||||||
|
|
||||||
override val isInstalled: Boolean by lazy {
|
|
||||||
// Using the builtin stuff here instead of Env because it should only scan for direnv on the process path
|
|
||||||
PathEnvironmentVariableUtil.findExecutableInPathOnAnyOS("direnv") != null
|
|
||||||
}
|
|
||||||
|
|
||||||
var isEnabledRaw: DirenvState
|
|
||||||
get() = state.enabled
|
|
||||||
set(value) {
|
|
||||||
updateState {
|
|
||||||
it.copy(enabled = value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override val isEnabled: DirenvState
|
|
||||||
get() = isEnabledRaw
|
|
||||||
|
|
||||||
override suspend fun import(): Env {
|
|
||||||
if (!isInstalled || !project.isTrusted() || project.isDefault)
|
|
||||||
return Env.empty
|
|
||||||
val workDir = project.guessProjectDir()?.toNioPath() ?: return Env.empty
|
|
||||||
|
|
||||||
val runOutput = run(workDir, "export", "json")
|
|
||||||
if (runOutput.error) {
|
|
||||||
if (runOutput.output.contains("is blocked")) {
|
|
||||||
Notifications.Bus.notify(Notification(
|
|
||||||
GROUP_DISPLAY_ID,
|
|
||||||
ZigBrainsBundle.message("notification.title.direnv-blocked"),
|
|
||||||
ZigBrainsBundle.message("notification.content.direnv-blocked"),
|
|
||||||
NotificationType.ERROR
|
|
||||||
))
|
|
||||||
return Env.empty
|
|
||||||
} else {
|
|
||||||
Notifications.Bus.notify(Notification(
|
|
||||||
GROUP_DISPLAY_ID,
|
|
||||||
ZigBrainsBundle.message("notification.title.direnv-error"),
|
|
||||||
ZigBrainsBundle.message("notification.content.direnv-error", runOutput.output),
|
|
||||||
NotificationType.ERROR
|
|
||||||
))
|
|
||||||
return Env.empty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return if (runOutput.output.isBlank()) {
|
|
||||||
Env.empty
|
|
||||||
} else {
|
|
||||||
Env(Json.decodeFromString<Map<String, String>>(runOutput.output))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun run(workDir: Path, vararg args: String): DirenvOutput {
|
|
||||||
val cli = GeneralCommandLine("direnv", *args).withWorkingDirectory(workDir)
|
|
||||||
|
|
||||||
val (process, exitCode) = withProgressText("Running ${cli.commandLineString}") {
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
mutex.withLock {
|
|
||||||
val process = cli.createProcess()
|
|
||||||
val exitCode = process.awaitExit()
|
|
||||||
process to exitCode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exitCode != 0) {
|
|
||||||
val stdErr = process.errorStream.bufferedReader().use { it.readText() }
|
|
||||||
return DirenvOutput(stdErr, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
val stdOut = process.inputStream.bufferedReader().use { it.readText() }
|
|
||||||
return DirenvOutput(stdOut, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun hasDotEnv(): Boolean {
|
|
||||||
if (!isInstalled)
|
|
||||||
return false
|
|
||||||
val projectDir = project.guessProjectDir()?.toNioPathOrNull() ?: return false
|
|
||||||
return envFiles.any { projectDir.resolve(it).isRegularFile() }
|
|
||||||
}
|
|
||||||
|
|
||||||
data class State(
|
|
||||||
@JvmField
|
|
||||||
@Attribute
|
|
||||||
var enabled: DirenvState = DirenvState.Auto
|
|
||||||
)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val GROUP_DISPLAY_ID = "zigbrains-direnv"
|
|
||||||
fun getInstance(project: Project): IDirenvService = project.service<DirenvService>()
|
|
||||||
|
|
||||||
private val STATE_KEY = Key.create<DirenvState>("DIRENV_STATE")
|
|
||||||
|
|
||||||
fun getStateFor(data: UserDataHolder?, project: Project?): DirenvState {
|
|
||||||
return data?.getUserData(STATE_KEY) ?: project?.let { getInstance(project).isEnabled } ?: DirenvState.Disabled
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setStateFor(data: UserDataHolder, state: DirenvState) {
|
|
||||||
data.putUserData(STATE_KEY, state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed interface IDirenvService {
|
|
||||||
val isInstalled: Boolean
|
|
||||||
val isEnabled: DirenvState
|
|
||||||
suspend fun import(): Env
|
|
||||||
}
|
|
||||||
|
|
||||||
private val envFiles = listOf(".envrc", ".env")
|
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.direnv
|
|
||||||
|
|
||||||
import com.intellij.openapi.components.service
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
|
|
||||||
enum class DirenvState {
|
|
||||||
Auto,
|
|
||||||
Enabled,
|
|
||||||
Disabled;
|
|
||||||
|
|
||||||
fun isEnabled(project: Project?): Boolean {
|
|
||||||
return when(this) {
|
|
||||||
Enabled -> true
|
|
||||||
Disabled -> false
|
|
||||||
Auto -> project?.service<DirenvService>()?.hasDotEnv() == true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.direnv
|
|
||||||
|
|
||||||
import com.intellij.openapi.util.SystemInfo
|
|
||||||
import com.intellij.openapi.util.io.toNioPathOrNull
|
|
||||||
import com.intellij.util.EnvironmentUtil
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.flow
|
|
||||||
import kotlinx.coroutines.flow.flowOn
|
|
||||||
import org.jetbrains.annotations.NonNls
|
|
||||||
import java.io.File
|
|
||||||
import kotlin.io.path.absolute
|
|
||||||
import kotlin.io.path.isDirectory
|
|
||||||
import kotlin.io.path.isExecutable
|
|
||||||
import kotlin.io.path.isRegularFile
|
|
||||||
|
|
||||||
@JvmRecord
|
|
||||||
data class Env(val env: Map<String, String>) {
|
|
||||||
private val path get() = getVariable("PATH")?.split(File.pathSeparatorChar)
|
|
||||||
|
|
||||||
private fun getVariable(name: @NonNls String) =
|
|
||||||
env.getOrElse(name) { EnvironmentUtil.getValue(name) }
|
|
||||||
|
|
||||||
fun findAllExecutablesOnPATH(exe: @NonNls String) = flow {
|
|
||||||
val exeName = if (SystemInfo.isWindows) "$exe.exe" else exe
|
|
||||||
val paths = path ?: return@flow
|
|
||||||
for (dir in paths) {
|
|
||||||
val path = dir.toNioPathOrNull()?.absolute() ?: continue
|
|
||||||
if (!path.toFile().exists() || !path.isDirectory())
|
|
||||||
continue
|
|
||||||
val exePath = path.resolve(exeName).absolute()
|
|
||||||
if (!exePath.isRegularFile() || !exePath.isExecutable())
|
|
||||||
continue
|
|
||||||
emit(exePath)
|
|
||||||
}
|
|
||||||
}.flowOn(Dispatchers.IO)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val empty = Env(emptyMap())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,101 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.direnv.ui
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
|
||||||
import com.falsepattern.zigbrains.direnv.DirenvService
|
|
||||||
import com.falsepattern.zigbrains.direnv.DirenvState
|
|
||||||
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider
|
|
||||||
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider.Companion.PROJECT_KEY
|
|
||||||
import com.falsepattern.zigbrains.shared.SubConfigurable
|
|
||||||
import com.intellij.openapi.components.service
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.ui.ComboBox
|
|
||||||
import com.intellij.ui.dsl.builder.Panel
|
|
||||||
import java.awt.event.ItemEvent
|
|
||||||
|
|
||||||
abstract class DirenvEditor<T>(private val sharedState: ZigProjectConfigurationProvider.IUserDataBridge?): SubConfigurable<T> {
|
|
||||||
private var cb: ComboBox<DirenvState>? = null
|
|
||||||
override fun attach(panel: Panel): Unit = with(panel) {
|
|
||||||
row(ZigBrainsBundle.message("settings.direnv.enable.label")) {
|
|
||||||
comboBox(DirenvState.entries).component.let {
|
|
||||||
cb = it
|
|
||||||
if (sharedState != null) {
|
|
||||||
it.addItemListener { e ->
|
|
||||||
if (e.stateChange != ItemEvent.SELECTED)
|
|
||||||
return@addItemListener
|
|
||||||
val item = e.item
|
|
||||||
if (item !is DirenvState)
|
|
||||||
return@addItemListener
|
|
||||||
DirenvService.setStateFor(sharedState, item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isModified(context: T): Boolean {
|
|
||||||
return isEnabled(context) != cb?.selectedItem as DirenvState
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun apply(context: T) {
|
|
||||||
setEnabled(context, cb?.selectedItem as DirenvState)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun reset(context: T?) {
|
|
||||||
if (context == null) {
|
|
||||||
cb?.selectedItem = DirenvState.Auto
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cb?.selectedItem = isEnabled(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun dispose() {
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun isEnabled(context: T): DirenvState
|
|
||||||
abstract fun setEnabled(context: T, value: DirenvState)
|
|
||||||
|
|
||||||
class ForProject(sharedState: ZigProjectConfigurationProvider.IUserDataBridge) : DirenvEditor<Project>(sharedState) {
|
|
||||||
override fun isEnabled(context: Project): DirenvState {
|
|
||||||
return DirenvService.getInstance(context).isEnabled
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setEnabled(context: Project, value: DirenvState) {
|
|
||||||
context.service<DirenvService>().isEnabledRaw = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Provider: ZigProjectConfigurationProvider {
|
|
||||||
override fun create(sharedState: ZigProjectConfigurationProvider.IUserDataBridge): SubConfigurable<Project>? {
|
|
||||||
if (sharedState.getUserData(PROJECT_KEY)?.isDefault != false) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
DirenvService.setStateFor(sharedState, DirenvState.Auto)
|
|
||||||
return ForProject(sharedState)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val index: Int
|
|
||||||
get() = 100
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.actions
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.Icons
|
|
||||||
import com.intellij.ide.actions.CreateFileFromTemplateAction
|
|
||||||
import com.intellij.ide.actions.CreateFileFromTemplateDialog
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.psi.PsiDirectory
|
|
||||||
|
|
||||||
class ZigNewFileAction: CreateFileFromTemplateAction() {
|
|
||||||
override fun buildDialog(project: Project, directory: PsiDirectory, builder: CreateFileFromTemplateDialog.Builder) {
|
|
||||||
builder.setTitle("Zig File")
|
|
||||||
.addKind("Empty file", Icons.Zig, "blank_zig_file")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getActionName(directory: PsiDirectory?, newName: String, templateName: String?): String {
|
|
||||||
return "Zig File"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.actions
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigExecConfig
|
|
||||||
import com.falsepattern.zigbrains.project.execution.run.ZigConfigProducerRun
|
|
||||||
import com.falsepattern.zigbrains.project.execution.run.ZigExecConfigRun
|
|
||||||
import com.falsepattern.zigbrains.project.execution.test.ZigConfigProducerTest
|
|
||||||
import com.falsepattern.zigbrains.project.execution.test.ZigExecConfigTest
|
|
||||||
import com.intellij.execution.ExecutionManager
|
|
||||||
import com.intellij.execution.actions.ConfigurationContext
|
|
||||||
import com.intellij.execution.actions.RunConfigurationProducer
|
|
||||||
import com.intellij.execution.executors.DefaultRunExecutor
|
|
||||||
import com.intellij.execution.runners.ExecutionEnvironmentBuilder
|
|
||||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
|
||||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
|
||||||
import com.intellij.openapi.project.DumbAwareAction
|
|
||||||
|
|
||||||
class ZigRunFileAction: DumbAwareAction() {
|
|
||||||
override fun actionPerformed(e: AnActionEvent) {
|
|
||||||
val file = e.getData(CommonDataKeys.PSI_FILE) ?: return
|
|
||||||
val config = getConfig(e) ?: return
|
|
||||||
val project = file.project
|
|
||||||
val builder = ExecutionEnvironmentBuilder.createOrNull(DefaultRunExecutor.getRunExecutorInstance(), config) ?: return
|
|
||||||
ExecutionManager.getInstance(project).restartRunProfile(builder.build())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getConfig(e: AnActionEvent): ZigExecConfig<*>? {
|
|
||||||
val context = ConfigurationContext.getFromContext(e.dataContext, e.place)
|
|
||||||
return getRunConfiguration(context) ?: getTestConfiguration(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update(e: AnActionEvent) {
|
|
||||||
e.presentation.isEnabledAndVisible = getConfig(e) != null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getRunConfiguration(context: ConfigurationContext): ZigExecConfigRun? {
|
|
||||||
try {
|
|
||||||
val configProducer = RunConfigurationProducer.getInstance(ZigConfigProducerRun::class.java)
|
|
||||||
val settings = configProducer.findExistingConfiguration(context)
|
|
||||||
if (settings != null) {
|
|
||||||
return settings.configuration as? ZigExecConfigRun
|
|
||||||
}
|
|
||||||
val fromContext = configProducer.createConfigurationFromContext(context)
|
|
||||||
if (fromContext != null) {
|
|
||||||
return fromContext.configuration as? ZigExecConfigRun
|
|
||||||
}
|
|
||||||
} catch (_: NullPointerException) {}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
private fun getTestConfiguration(context: ConfigurationContext): ZigExecConfigTest? {
|
|
||||||
try {
|
|
||||||
val configProducer = RunConfigurationProducer.getInstance(ZigConfigProducerTest::class.java)
|
|
||||||
val settings = configProducer.findExistingConfiguration(context)
|
|
||||||
if (settings != null) {
|
|
||||||
return settings.configuration as? ZigExecConfigTest
|
|
||||||
}
|
|
||||||
val fromContext = configProducer.createConfigurationFromContext(context)
|
|
||||||
if (fromContext != null) {
|
|
||||||
return fromContext.configuration as? ZigExecConfigTest
|
|
||||||
}
|
|
||||||
} catch (_: NullPointerException) {}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getActionUpdateThread(): ActionUpdateThread {
|
|
||||||
return ActionUpdateThread.BGT
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.console
|
|
||||||
|
|
||||||
import com.intellij.execution.filters.ConsoleFilterProvider
|
|
||||||
import com.intellij.execution.filters.Filter
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
|
|
||||||
class ZigConsoleFilterProvider: ConsoleFilterProvider {
|
|
||||||
override fun getDefaultFilters(project: Project): Array<Filter> {
|
|
||||||
return arrayOf(ZigSourceFileFilter(project))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,82 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.console
|
|
||||||
|
|
||||||
import com.intellij.execution.filters.Filter
|
|
||||||
import com.intellij.execution.filters.Filter.ResultItem
|
|
||||||
import com.intellij.execution.filters.OpenFileHyperlinkInfo
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.project.guessProjectDir
|
|
||||||
import com.intellij.openapi.vfs.refreshAndFindVirtualFile
|
|
||||||
import com.intellij.openapi.vfs.toNioPathOrNull
|
|
||||||
import java.io.File
|
|
||||||
import java.nio.file.InvalidPathException
|
|
||||||
import java.nio.file.Path
|
|
||||||
import kotlin.math.max
|
|
||||||
|
|
||||||
|
|
||||||
class ZigSourceFileFilter(private val project: Project): Filter {
|
|
||||||
private val projectPath = runCatching { project.guessProjectDir()?.toNioPathOrNull()?.toFile() }.getOrNull()
|
|
||||||
override fun applyFilter(line: String, entireLength: Int): Filter.Result? {
|
|
||||||
val lineStart = entireLength - line.length
|
|
||||||
val results = ArrayList<ResultItem>()
|
|
||||||
val matcher = LEN_REGEX.findAll(line)
|
|
||||||
for (match in matcher) {
|
|
||||||
val start = match.range.first
|
|
||||||
val pair = findLongestParsablePathFromOffset(line, start)
|
|
||||||
val path = pair?.first ?: return null
|
|
||||||
val file = path.refreshAndFindVirtualFile() ?: return null
|
|
||||||
val lineNumber = max(match.groups[1]!!.value.toInt() - 1, 0)
|
|
||||||
val lineOffset = max(match.groups[2]!!.value.toInt() - 1, 0)
|
|
||||||
results.add(ResultItem(lineStart + pair.second, lineStart + match.range.last + 1, OpenFileHyperlinkInfo(project, file, lineNumber, lineOffset)))
|
|
||||||
}
|
|
||||||
return Filter.Result(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findLongestParsablePathFromOffset(line: String, end: Int): Pair<Path, Int>? {
|
|
||||||
var longestStart = -1
|
|
||||||
var longest: File? = null
|
|
||||||
for (i in end - 1 downTo 0) {
|
|
||||||
try {
|
|
||||||
val pathStr = line.substring(i, end)
|
|
||||||
var file = File(pathStr)
|
|
||||||
if (!file.isFile) {
|
|
||||||
if (projectPath == null) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
file = projectPath.resolve(pathStr)
|
|
||||||
if (!file.isFile) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
longest = file
|
|
||||||
longestStart = i
|
|
||||||
} catch (ignored: InvalidPathException) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
longest ?: return null
|
|
||||||
return Pair(longest.toPath(), longestStart)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val LEN_REGEX = Regex(":(\\d+):(\\d+)")
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution
|
|
||||||
|
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
|
||||||
import com.intellij.execution.configurations.ConfigurationTypeBase
|
|
||||||
import com.intellij.execution.configurations.runConfigurationType
|
|
||||||
|
|
||||||
inline fun <reified T: ConfigurationTypeBase> firstConfigFactory(): ConfigurationFactory {
|
|
||||||
return runConfigurationType<T>().configurationFactories.first()
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution
|
|
||||||
|
|
||||||
import com.intellij.execution.filters.TextConsoleBuilderImpl
|
|
||||||
import com.intellij.execution.ui.ConsoleView
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.terminal.TerminalExecutionConsole
|
|
||||||
|
|
||||||
class ZigConsoleBuilder(private val project: Project, private val emulateTerminal: Boolean = false): TextConsoleBuilderImpl(project) {
|
|
||||||
override fun createConsole(): ConsoleView {
|
|
||||||
return if (emulateTerminal)
|
|
||||||
TerminalExecutionConsole(project, null)
|
|
||||||
else
|
|
||||||
super.createConsole()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,384 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.base
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigConfigurable.ZigConfigModule
|
|
||||||
import com.falsepattern.zigbrains.shared.cli.translateCommandline
|
|
||||||
import com.falsepattern.zigbrains.shared.element.*
|
|
||||||
import com.intellij.openapi.Disposable
|
|
||||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
|
|
||||||
import com.intellij.openapi.options.SettingsEditor
|
|
||||||
import com.intellij.openapi.ui.ComboBox
|
|
||||||
import com.intellij.openapi.util.Disposer
|
|
||||||
import com.intellij.openapi.util.io.toNioPathOrNull
|
|
||||||
import com.intellij.ui.components.JBCheckBox
|
|
||||||
import com.intellij.ui.components.JBTextField
|
|
||||||
import com.intellij.ui.components.textFieldWithBrowseButton
|
|
||||||
import com.intellij.ui.dsl.builder.AlignX
|
|
||||||
import com.intellij.ui.dsl.builder.Panel
|
|
||||||
import com.intellij.ui.dsl.builder.panel
|
|
||||||
import org.jdom.Element
|
|
||||||
import org.jetbrains.annotations.Nls
|
|
||||||
import java.io.Serializable
|
|
||||||
import java.nio.file.Path
|
|
||||||
import javax.swing.JComponent
|
|
||||||
import kotlin.io.path.pathString
|
|
||||||
|
|
||||||
class ZigConfigEditor<T : ZigExecConfig<T>>(private val state: ZigExecConfig<T>) : SettingsEditor<T>() {
|
|
||||||
private val configModules = ArrayList<ZigConfigModule<*>>()
|
|
||||||
|
|
||||||
override fun resetEditorFrom(s: T) {
|
|
||||||
outer@ for (cfg in s.getConfigurables()) {
|
|
||||||
for (module in configModules) {
|
|
||||||
if (module.tryReset(cfg))
|
|
||||||
continue@outer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun applyEditorTo(s: T) {
|
|
||||||
outer@ for (cfg in s.getConfigurables()) {
|
|
||||||
for (module in configModules) {
|
|
||||||
if (module.tryApply(cfg)) {
|
|
||||||
continue@outer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createEditor(): JComponent {
|
|
||||||
configModules.clear()
|
|
||||||
configModules.addAll(state.getConfigurables().map { it.createEditor() })
|
|
||||||
return panel {
|
|
||||||
for (module in configModules) {
|
|
||||||
module.construct(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun disposeEditor() {
|
|
||||||
for (module in configModules) {
|
|
||||||
module.dispose()
|
|
||||||
}
|
|
||||||
configModules.clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ZigConfigurable<T : ZigConfigurable<T>> : Serializable, Cloneable {
|
|
||||||
fun readExternal(element: Element)
|
|
||||||
fun writeExternal(element: Element)
|
|
||||||
fun createEditor(): ZigConfigModule<T>
|
|
||||||
public override fun clone(): T
|
|
||||||
|
|
||||||
interface ZigConfigModule<T : ZigConfigurable<T>> : Disposable {
|
|
||||||
fun tryMatch(cfg: ZigConfigurable<*>): T?
|
|
||||||
fun apply(configurable: T): Boolean
|
|
||||||
fun reset(configurable: T)
|
|
||||||
fun tryApply(cfg: ZigConfigurable<*>): Boolean {
|
|
||||||
val x = tryMatch(cfg)
|
|
||||||
if (x != null) {
|
|
||||||
return apply(x)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun tryReset(cfg: ZigConfigurable<*>): Boolean {
|
|
||||||
val x = tryMatch(cfg)
|
|
||||||
if (x != null) {
|
|
||||||
reset(x)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun construct(p: Panel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class PathConfigurable<T : PathConfigurable<T>> : ZigConfigurable<T> {
|
|
||||||
var path: Path? = null
|
|
||||||
|
|
||||||
override fun readExternal(element: Element) {
|
|
||||||
path = element.readString(serializedName)?.ifBlank { null }?.toNioPathOrNull() ?: return
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun writeExternal(element: Element) {
|
|
||||||
element.writeString(serializedName, path?.pathString ?: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract val serializedName: String
|
|
||||||
|
|
||||||
abstract class PathConfigModule<T : PathConfigurable<T>> : ZigConfigModule<T> {
|
|
||||||
override fun apply(configurable: T): Boolean {
|
|
||||||
val str = stringValue
|
|
||||||
if (str.isBlank()) {
|
|
||||||
configurable.path = null
|
|
||||||
} else {
|
|
||||||
configurable.path = str.toNioPathOrNull() ?: return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun reset(configurable: T) {
|
|
||||||
stringValue = configurable.path?.pathString ?: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract var stringValue: String
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WorkDirectoryConfigurable(@Transient override val serializedName: String) : PathConfigurable<WorkDirectoryConfigurable>(), Cloneable {
|
|
||||||
override fun createEditor(): ZigConfigModule<WorkDirectoryConfigurable> {
|
|
||||||
return WorkDirectoryConfigModule(serializedName)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clone(): WorkDirectoryConfigurable {
|
|
||||||
return super<Cloneable>.clone() as WorkDirectoryConfigurable
|
|
||||||
}
|
|
||||||
|
|
||||||
class WorkDirectoryConfigModule(private val serializedName: String) : PathConfigModule<WorkDirectoryConfigurable>() {
|
|
||||||
private val field = textFieldWithBrowseButton(
|
|
||||||
null,
|
|
||||||
FileChooserDescriptorFactory.createSingleFolderDescriptor().withTitle(ZigBrainsBundle.message("dialog.title.working-directory"))
|
|
||||||
).also { Disposer.register(this, it) }
|
|
||||||
|
|
||||||
override var stringValue by field::text
|
|
||||||
|
|
||||||
override fun tryMatch(cfg: ZigConfigurable<*>): WorkDirectoryConfigurable? {
|
|
||||||
return if (cfg is WorkDirectoryConfigurable && cfg.serializedName == serializedName) cfg else null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun construct(p: Panel): Unit = with(p) {
|
|
||||||
row(ZigBrainsBundle.message("exec.option.label.working-directory")) {
|
|
||||||
cell(field).resizableColumn().align(AlignX.FILL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun dispose() {
|
|
||||||
field.dispose()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FilePathConfigurable(
|
|
||||||
@Transient override val serializedName: String,
|
|
||||||
@Transient @Nls private val guiLabel: String
|
|
||||||
) : PathConfigurable<FilePathConfigurable>(), Cloneable {
|
|
||||||
|
|
||||||
override fun createEditor(): ZigConfigModule<FilePathConfigurable> {
|
|
||||||
return FilePathConfigModule(serializedName, guiLabel)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clone(): FilePathConfigurable {
|
|
||||||
return super<Cloneable>.clone() as FilePathConfigurable
|
|
||||||
}
|
|
||||||
|
|
||||||
class FilePathConfigModule(private val serializedName: String, @Nls private val label: String) : PathConfigModule<FilePathConfigurable>() {
|
|
||||||
private val field = textFieldWithBrowseButton(
|
|
||||||
null,
|
|
||||||
FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor(),
|
|
||||||
)
|
|
||||||
|
|
||||||
override var stringValue by field::text
|
|
||||||
|
|
||||||
override fun tryMatch(cfg: ZigConfigurable<*>): FilePathConfigurable? {
|
|
||||||
return if (cfg is FilePathConfigurable && cfg.serializedName == serializedName) cfg else null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun construct(p: Panel): Unit = with(p) {
|
|
||||||
row(label) {
|
|
||||||
cell(field).resizableColumn().align(AlignX.FILL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun dispose() {
|
|
||||||
Disposer.dispose(field)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open class CheckboxConfigurable(
|
|
||||||
@Transient private val serializedName: String,
|
|
||||||
@Transient @Nls private val label: String,
|
|
||||||
var value: Boolean
|
|
||||||
) : ZigConfigurable<CheckboxConfigurable>, Cloneable {
|
|
||||||
override fun readExternal(element: Element) {
|
|
||||||
value = element.readBoolean(serializedName) ?: return
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun writeExternal(element: Element) {
|
|
||||||
element.writeBoolean(serializedName, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createEditor(): ZigConfigModule<CheckboxConfigurable> {
|
|
||||||
return CheckboxConfigModule(serializedName, label)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clone(): CheckboxConfigurable {
|
|
||||||
return super<Cloneable>.clone() as CheckboxConfigurable
|
|
||||||
}
|
|
||||||
|
|
||||||
class CheckboxConfigModule(
|
|
||||||
private val serializedName: String,
|
|
||||||
@Nls private val label: String
|
|
||||||
) : ZigConfigModule<CheckboxConfigurable> {
|
|
||||||
private val checkBox = JBCheckBox()
|
|
||||||
|
|
||||||
override fun tryMatch(cfg: ZigConfigurable<*>): CheckboxConfigurable? {
|
|
||||||
return if (cfg is CheckboxConfigurable && cfg.serializedName == serializedName) cfg else null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun apply(configurable: CheckboxConfigurable): Boolean {
|
|
||||||
configurable.value = checkBox.isSelected
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun reset(configurable: CheckboxConfigurable) {
|
|
||||||
checkBox.isSelected = configurable.value
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun construct(p: Panel): Unit = with(p) {
|
|
||||||
row(label) {
|
|
||||||
cell(checkBox)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun dispose() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class OptimizationConfigurable(
|
|
||||||
@Transient private val serializedName: String,
|
|
||||||
var level: OptimizationLevel = OptimizationLevel.Debug,
|
|
||||||
var forced: Boolean = false
|
|
||||||
) : ZigConfigurable<OptimizationConfigurable>, Cloneable {
|
|
||||||
override fun readExternal(element: Element) {
|
|
||||||
element.readChild(serializedName)?.apply {
|
|
||||||
readEnum<OptimizationLevel>("level")?.let { level = it }
|
|
||||||
readBoolean("forced")?.let { forced = it }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun writeExternal(element: Element) {
|
|
||||||
element.writeChild(serializedName).apply {
|
|
||||||
writeEnum("level", level)
|
|
||||||
writeBoolean("forced", forced)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createEditor(): ZigConfigModule<OptimizationConfigurable> {
|
|
||||||
return OptimizationConfigModule(serializedName)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clone(): OptimizationConfigurable {
|
|
||||||
return super<Cloneable>.clone() as OptimizationConfigurable
|
|
||||||
}
|
|
||||||
|
|
||||||
class OptimizationConfigModule(private val serializedName: String) : ZigConfigModule<OptimizationConfigurable> {
|
|
||||||
private val levels = ComboBox(OptimizationLevel.entries.toTypedArray())
|
|
||||||
private val forced = JBCheckBox(ZigBrainsBundle.message("exec.option.label.optimization.force"))
|
|
||||||
override fun tryMatch(cfg: ZigConfigurable<*>): OptimizationConfigurable? {
|
|
||||||
return if (cfg is OptimizationConfigurable && cfg.serializedName == serializedName) cfg else null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun apply(configurable: OptimizationConfigurable): Boolean {
|
|
||||||
configurable.level = levels.item
|
|
||||||
configurable.forced = forced.isSelected
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun reset(configurable: OptimizationConfigurable) {
|
|
||||||
levels.item = configurable.level
|
|
||||||
forced.isSelected = configurable.forced
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun construct(p: Panel): Unit = with(p) {
|
|
||||||
row(ZigBrainsBundle.message("exec.option.label.optimization")) {
|
|
||||||
cell(levels)
|
|
||||||
cell(forced)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun dispose() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ArgsConfigurable(
|
|
||||||
@Transient private val serializedName: String,
|
|
||||||
@Transient @Nls private val guiName: String
|
|
||||||
) : ZigConfigurable<ArgsConfigurable>, Cloneable {
|
|
||||||
var args: String = ""
|
|
||||||
|
|
||||||
override fun readExternal(element: Element) {
|
|
||||||
args = element.readString(serializedName) ?: element.readStrings(serializedName)?.joinToString(separator = " ") { if (it.contains(' ')) "\"$it\"" else it } ?: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
fun argsSplit(): List<String> {
|
|
||||||
return translateCommandline(args)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun writeExternal(element: Element) {
|
|
||||||
element.writeString(serializedName, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createEditor(): ZigConfigModule<ArgsConfigurable> {
|
|
||||||
return ArgsConfigModule(serializedName, guiName)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clone(): ArgsConfigurable {
|
|
||||||
return super<Cloneable>.clone() as ArgsConfigurable
|
|
||||||
}
|
|
||||||
|
|
||||||
class ArgsConfigModule(
|
|
||||||
private val serializedName: String,
|
|
||||||
@Nls private val guiName: String
|
|
||||||
) : ZigConfigModule<ArgsConfigurable> {
|
|
||||||
private val argsField = JBTextField()
|
|
||||||
|
|
||||||
override fun tryMatch(cfg: ZigConfigurable<*>): ArgsConfigurable? {
|
|
||||||
return if (cfg is ArgsConfigurable && cfg.serializedName == serializedName) cfg else null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun apply(configurable: ArgsConfigurable): Boolean {
|
|
||||||
configurable.args = argsField.text ?: ""
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun reset(configurable: ArgsConfigurable) {
|
|
||||||
argsField.text = configurable.args
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun construct(p: Panel): Unit = with(p) {
|
|
||||||
row(guiName) {
|
|
||||||
cell(argsField).resizableColumn().align(AlignX.FILL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun dispose() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.base
|
|
||||||
|
|
||||||
enum class OptimizationLevel {
|
|
||||||
Debug,
|
|
||||||
ReleaseSafe,
|
|
||||||
ReleaseFast,
|
|
||||||
ReleaseSmall
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.base
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.zig.psi.ZigFile
|
|
||||||
import com.intellij.execution.actions.ConfigurationContext
|
|
||||||
import com.intellij.execution.actions.ConfigurationFromContext
|
|
||||||
import com.intellij.execution.actions.LazyRunConfigurationProducer
|
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
|
||||||
import com.intellij.openapi.util.Ref
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
|
||||||
import com.intellij.openapi.vfs.toNioPathOrNull
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
abstract class ZigConfigProducer<T: ZigExecConfig<T>>: LazyRunConfigurationProducer<T>() {
|
|
||||||
abstract override fun getConfigurationFactory(): ConfigurationFactory
|
|
||||||
|
|
||||||
override fun setupConfigurationFromContext(configuration: T, context: ConfigurationContext, sourceElement: Ref<PsiElement>): Boolean {
|
|
||||||
val element = context.location?.psiElement ?: return false
|
|
||||||
val psiFile = element.containingFile as? ZigFile ?: return false
|
|
||||||
val theFile = psiFile.virtualFile ?: return false
|
|
||||||
val filePath = theFile.toNioPathOrNull() ?: return false
|
|
||||||
return setupConfigurationFromContext(configuration, element, psiFile, filePath, theFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isConfigurationFromContext(configuration: T, context: ConfigurationContext): Boolean {
|
|
||||||
val element = context.location?.psiElement ?: return false
|
|
||||||
val psiFile = element.containingFile as? ZigFile ?: return false
|
|
||||||
val theFile = psiFile.virtualFile ?: return false
|
|
||||||
val filePath = theFile.toNioPathOrNull() ?: return false
|
|
||||||
return isConfigurationFromContext(configuration, element, psiFile, filePath, theFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
TODO implement these
|
|
||||||
@Override
|
|
||||||
protected boolean setupConfigurationFromContext(@NotNull ZigExecConfigRun configuration, PsiElement element, String filePath, VirtualFile theFile) {
|
|
||||||
if (PsiUtil.getElementType(element) == ZigTypes.KEYWORD_TEST) {
|
|
||||||
configuration.command = "test " + filePath;
|
|
||||||
configuration.setName("Test " + theFile.getPresentableName());
|
|
||||||
} else if ("build.zig".equals(theFile.getName())) {
|
|
||||||
configuration.command = "build";
|
|
||||||
configuration.setName("Build");
|
|
||||||
} else {
|
|
||||||
configuration.extraArgs = filePath;
|
|
||||||
configuration.setName(theFile.getPresentableName());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isConfigurationFromContext(@NotNull ZigExecConfigRun configuration, String filePath, VirtualFile vFile, PsiElement element) {
|
|
||||||
if (!configuration.command.contains(filePath)) {
|
|
||||||
return configuration.command.startsWith("build") && vFile.getName().equals("build.zig");
|
|
||||||
}
|
|
||||||
return (PsiUtil.getElementType(element) == ZigTypes.KEYWORD_TEST) == configuration.command.startsWith("test ");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
protected abstract fun setupConfigurationFromContext(configuration: T, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean
|
|
||||||
protected abstract fun isConfigurationFromContext(configuration: T, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean
|
|
||||||
abstract override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.base
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.direnv.DirenvService
|
|
||||||
import com.intellij.execution.ExecutionException
|
|
||||||
import com.intellij.execution.Executor
|
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
|
||||||
import com.intellij.execution.configurations.GeneralCommandLine
|
|
||||||
import com.intellij.execution.configurations.LocatableConfigurationBase
|
|
||||||
import com.intellij.execution.configurations.RunConfiguration
|
|
||||||
import com.intellij.execution.runners.ExecutionEnvironment
|
|
||||||
import com.intellij.openapi.options.SettingsEditor
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.project.guessProjectDir
|
|
||||||
import com.intellij.openapi.util.NlsActions.ActionText
|
|
||||||
import com.intellij.openapi.vfs.toNioPathOrNull
|
|
||||||
import org.jdom.Element
|
|
||||||
import org.jetbrains.annotations.Nls
|
|
||||||
|
|
||||||
abstract class ZigExecConfig<T: ZigExecConfig<T>>(project: Project, factory: ConfigurationFactory, @Nls name: String): LocatableConfigurationBase<ZigProfileState<T>>(project, factory, name) {
|
|
||||||
var workingDirectory = WorkDirectoryConfigurable("workingDirectory").apply { path = project.guessProjectDir()?.toNioPathOrNull() }
|
|
||||||
private set
|
|
||||||
|
|
||||||
abstract val suggestedName: @ActionText String
|
|
||||||
@Throws(ExecutionException::class)
|
|
||||||
abstract suspend fun buildCommandLineArgs(debug: Boolean): List<String>
|
|
||||||
abstract override fun getState(executor: Executor, environment: ExecutionEnvironment): ZigProfileState<T>
|
|
||||||
|
|
||||||
override fun getConfigurationEditor(): SettingsEditor<out RunConfiguration> {
|
|
||||||
return ZigConfigEditor(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun readExternal(element: Element) {
|
|
||||||
super.readExternal(element)
|
|
||||||
getConfigurables().forEach { it.readExternal(element) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun writeExternal(element: Element) {
|
|
||||||
super.writeExternal(element)
|
|
||||||
getConfigurables().forEach { it.writeExternal(element) }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
suspend fun patchCommandLine(commandLine: GeneralCommandLine): GeneralCommandLine {
|
|
||||||
val direnv = DirenvService.getInstance(project)
|
|
||||||
if (direnv.isEnabled.isEnabled(project)) {
|
|
||||||
commandLine.withEnvironment(direnv.import().env)
|
|
||||||
}
|
|
||||||
return commandLine
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clone(): T {
|
|
||||||
val myClone = super.clone() as ZigExecConfig<*>
|
|
||||||
myClone.workingDirectory = workingDirectory.clone()
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
return myClone as T
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun getConfigurables(): List<ZigConfigurable<*>> = listOf(workingDirectory)
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.base
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
|
||||||
import com.falsepattern.zigbrains.project.execution.ZigConsoleBuilder
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainService
|
|
||||||
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
|
|
||||||
import com.falsepattern.zigbrains.shared.cli.startIPCAwareProcess
|
|
||||||
import com.falsepattern.zigbrains.shared.coroutine.runModalOrBlocking
|
|
||||||
import com.intellij.execution.ExecutionException
|
|
||||||
import com.intellij.execution.configurations.CommandLineState
|
|
||||||
import com.intellij.execution.configurations.GeneralCommandLine
|
|
||||||
import com.intellij.execution.configurations.PtyCommandLine
|
|
||||||
import com.intellij.execution.process.ProcessHandler
|
|
||||||
import com.intellij.execution.runners.ExecutionEnvironment
|
|
||||||
import com.intellij.platform.ide.progress.ModalTaskOwner
|
|
||||||
import kotlin.io.path.pathString
|
|
||||||
|
|
||||||
abstract class ZigProfileState<T: ZigExecConfig<T>> (
|
|
||||||
environment: ExecutionEnvironment,
|
|
||||||
val configuration: T
|
|
||||||
): CommandLineState(environment) {
|
|
||||||
|
|
||||||
init {
|
|
||||||
consoleBuilder = ZigConsoleBuilder(environment.project, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(ExecutionException::class)
|
|
||||||
override fun startProcess(): ProcessHandler {
|
|
||||||
return runModalOrBlocking({ModalTaskOwner.project(environment.project)}, {"ZigProfileState.startProcess"}) {
|
|
||||||
startProcessSuspend()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(ExecutionException::class)
|
|
||||||
suspend fun startProcessSuspend(): ProcessHandler {
|
|
||||||
val toolchain = ZigToolchainService.getInstance(environment.project).toolchain ?: throw ExecutionException(ZigBrainsBundle.message("exception.zig-profile-state.start-process.no-toolchain"))
|
|
||||||
return getCommandLine(toolchain, false).startIPCAwareProcess(environment.project, emulateTerminal = true)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(ExecutionException::class)
|
|
||||||
open suspend fun getCommandLine(toolchain: ZigToolchain, debug: Boolean): GeneralCommandLine {
|
|
||||||
val workingDir = configuration.workingDirectory
|
|
||||||
val zigExePath = toolchain.zig.path()
|
|
||||||
|
|
||||||
val cli = PtyCommandLine().withConsoleMode(false)
|
|
||||||
cli.withExePath(zigExePath.pathString)
|
|
||||||
workingDir.path?.let { cli.withWorkingDirectory(it) }
|
|
||||||
cli.withCharset(Charsets.UTF_8)
|
|
||||||
cli.addParameters(configuration.buildCommandLineArgs(debug))
|
|
||||||
return configuration.patchCommandLine(cli)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.base
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.zig.psi.ZigTypes
|
|
||||||
import com.intellij.execution.lineMarker.ExecutorAction
|
|
||||||
import com.intellij.execution.lineMarker.RunLineMarkerContributor
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.psi.PsiFile
|
|
||||||
import com.intellij.psi.util.elementType
|
|
||||||
import javax.swing.Icon
|
|
||||||
|
|
||||||
abstract class ZigTopLevelLineMarker: RunLineMarkerContributor() {
|
|
||||||
private fun getParentIfTopLevel(element: PsiElement): PsiElement? {
|
|
||||||
var parent = getDeclaration(element)
|
|
||||||
|
|
||||||
var nestingLevel = 0
|
|
||||||
while (parent != null && parent !is PsiFile) {
|
|
||||||
if (parent.elementType == ZigTypes.CONTAINER_DECLARATION) {
|
|
||||||
if (nestingLevel != 0)
|
|
||||||
return null
|
|
||||||
nestingLevel++
|
|
||||||
}
|
|
||||||
parent = parent.parent
|
|
||||||
}
|
|
||||||
if (nestingLevel != 1)
|
|
||||||
return null
|
|
||||||
return parent
|
|
||||||
}
|
|
||||||
|
|
||||||
fun elementMatches(element: PsiElement): Boolean {
|
|
||||||
return getParentIfTopLevel(element) != null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getInfo(element: PsiElement): Info? {
|
|
||||||
if (!elementMatches(element))
|
|
||||||
return null
|
|
||||||
val actions = ExecutorAction.getActions(0)
|
|
||||||
return Info(getIcon(element), actions, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun getDeclaration(element: PsiElement): PsiElement?
|
|
||||||
|
|
||||||
abstract fun getIcon(element: PsiElement): Icon
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.base
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.zig.psi.ZigContainerMembers
|
|
||||||
import com.falsepattern.zigbrains.zig.psi.ZigFile
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
|
||||||
import com.intellij.openapi.vfs.isFile
|
|
||||||
import com.intellij.psi.util.childrenOfType
|
|
||||||
|
|
||||||
fun ZigFile.hasMainFunction(): Boolean {
|
|
||||||
val members = childrenOfType<ZigContainerMembers>().firstOrNull() ?: return false
|
|
||||||
return members.containerDeclarationList.any { it.decl?.fnProto?.identifier?.textMatches("main") == true }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ZigFile.hasTests(): Boolean {
|
|
||||||
val members = childrenOfType<ZigContainerMembers>().firstOrNull() ?: return false
|
|
||||||
return members.containerDeclarationList.any { it.testDecl != null }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun VirtualFile.findBuildZig(): VirtualFile? {
|
|
||||||
var parent = this.parent
|
|
||||||
while (parent != null) {
|
|
||||||
parent.children.forEach {
|
|
||||||
if (it.isFile && it.name == "build.zig") {
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
parent = parent.parent
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun VirtualFile.isBuildZig(): Boolean {
|
|
||||||
return name == "build.zig"
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.build
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigConfigProducer
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.findBuildZig
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.isBuildZig
|
|
||||||
import com.falsepattern.zigbrains.project.execution.firstConfigFactory
|
|
||||||
import com.falsepattern.zigbrains.zig.psi.ZigFile
|
|
||||||
import com.falsepattern.zigbrains.zig.psi.ZigTypes
|
|
||||||
import com.intellij.execution.actions.ConfigurationFromContext
|
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.psi.util.elementType
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
class ZigConfigProducerBuild: ZigConfigProducer<ZigExecConfigBuild>() {
|
|
||||||
override fun getConfigurationFactory(): ConfigurationFactory {
|
|
||||||
return firstConfigFactory<ZigConfigTypeBuild>()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setupConfigurationFromContext(configuration: ZigExecConfigBuild, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
|
|
||||||
if (theFile.isBuildZig()) {
|
|
||||||
configuration.name = ZigBrainsBundle.message("configuration.build.marker-run")
|
|
||||||
configuration.buildSteps.args = "run"
|
|
||||||
configuration.debugBuildSteps.args = "install"
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
val buildZig = theFile.findBuildZig() ?: return false
|
|
||||||
configuration.workingDirectory.path = buildZig.parent.toNioPath()
|
|
||||||
if (element.elementType == ZigTypes.KEYWORD_TEST) {
|
|
||||||
configuration.name = ZigBrainsBundle.message("configuration.build.marker-test")
|
|
||||||
configuration.buildSteps.args = "test"
|
|
||||||
configuration.debugBuildSteps.args = "install_test"
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
configuration.name = ZigBrainsBundle.message("configuration.build.marker-run")
|
|
||||||
configuration.buildSteps.args = "run"
|
|
||||||
configuration.debugBuildSteps.args = "install"
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isConfigurationFromContext(configuration: ZigExecConfigBuild, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
|
|
||||||
val dir = configuration.workingDirectory.path ?: return false
|
|
||||||
if (theFile.isBuildZig()) {
|
|
||||||
return filePath.parent == dir
|
|
||||||
} else {
|
|
||||||
if (element.elementType == ZigTypes.KEYWORD_TEST) {
|
|
||||||
if (configuration.buildSteps.args != "test")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
val buildZig = theFile.findBuildZig() ?: return false
|
|
||||||
return buildZig.parent.toNioPath() == dir
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
|
|
||||||
return self.configurationType is ZigConfigTypeBuild
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.build
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.Icons
|
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
|
||||||
import com.intellij.execution.configurations.ConfigurationTypeBase
|
|
||||||
import com.intellij.execution.configurations.RunConfiguration
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
|
|
||||||
class ZigConfigTypeBuild : ConfigurationTypeBase(
|
|
||||||
IDENTIFIER,
|
|
||||||
ZigBrainsBundle.message("configuration.build.name"),
|
|
||||||
ZigBrainsBundle.message("configuration.build.description"),
|
|
||||||
Icons.Zig
|
|
||||||
) {
|
|
||||||
init {
|
|
||||||
addFactory(ConfigFactoryRun(this))
|
|
||||||
}
|
|
||||||
|
|
||||||
class ConfigFactoryRun(type: ZigConfigTypeBuild): ConfigurationFactory(type) {
|
|
||||||
override fun createTemplateConfiguration(project: Project): RunConfiguration {
|
|
||||||
return ZigExecConfigBuild(project, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getId(): String {
|
|
||||||
return IDENTIFIER
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private const val IDENTIFIER = "ZIGBRAINS_BUILD"
|
|
|
@ -1,82 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.build
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.*
|
|
||||||
import com.falsepattern.zigbrains.shared.ZBFeatures
|
|
||||||
import com.intellij.execution.ExecutionException
|
|
||||||
import com.intellij.execution.Executor
|
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
|
||||||
import com.intellij.execution.runners.ExecutionEnvironment
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
|
|
||||||
class ZigExecConfigBuild(project: Project, factory: ConfigurationFactory): ZigExecConfig<ZigExecConfigBuild>(project, factory, ZigBrainsBundle.message("exec.type.build.label")) {
|
|
||||||
var buildSteps = ArgsConfigurable("buildSteps", ZigBrainsBundle.message("exec.option.label.build.steps"))
|
|
||||||
private set
|
|
||||||
var extraArgs = ArgsConfigurable("compilerArgs", ZigBrainsBundle.message("exec.option.label.build.args"))
|
|
||||||
private set
|
|
||||||
var debugBuildSteps = ArgsConfigurable("debugBuildSteps", ZigBrainsBundle.message("exec.option.label.build.steps-debug"))
|
|
||||||
private set
|
|
||||||
var debugExtraArgs = ArgsConfigurable("debugCompilerArgs", ZigBrainsBundle.message("exec.option.label.build.args-debug"))
|
|
||||||
private set
|
|
||||||
var exePath = FilePathConfigurable("exePath", ZigBrainsBundle.message("exec.option.label.build.exe-path-debug"))
|
|
||||||
private set
|
|
||||||
var exeArgs = ArgsConfigurable("exeArgs", ZigBrainsBundle.message("exec.option.label.build.exe-args-debug"))
|
|
||||||
private set
|
|
||||||
|
|
||||||
@Throws(ExecutionException::class)
|
|
||||||
override suspend fun buildCommandLineArgs(debug: Boolean): List<String> {
|
|
||||||
val result = ArrayList<String>()
|
|
||||||
result.add("build")
|
|
||||||
val steps = if (debug) debugBuildSteps.argsSplit() else buildSteps.argsSplit()
|
|
||||||
result.addAll(steps)
|
|
||||||
result.addAll(if (debug) debugExtraArgs.argsSplit() else extraArgs.argsSplit())
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
override val suggestedName: String
|
|
||||||
get() = ZigBrainsBundle.message("configuration.build.suggested-name")
|
|
||||||
|
|
||||||
override fun clone(): ZigExecConfigBuild {
|
|
||||||
val clone = super.clone()
|
|
||||||
clone.buildSteps = buildSteps.clone()
|
|
||||||
clone.exeArgs = exeArgs.clone()
|
|
||||||
clone.exePath = exePath.clone()
|
|
||||||
clone.exeArgs = exeArgs.clone()
|
|
||||||
return clone
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getConfigurables(): List<ZigConfigurable<*>> {
|
|
||||||
val baseCfg = super.getConfigurables() + listOf(buildSteps, extraArgs)
|
|
||||||
return if (ZBFeatures.debug()) {
|
|
||||||
baseCfg + listOf(debugBuildSteps, debugExtraArgs, exePath, exeArgs)
|
|
||||||
} else {
|
|
||||||
baseCfg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getState(executor: Executor, environment: ExecutionEnvironment): ZigProfileState<ZigExecConfigBuild> {
|
|
||||||
return ZigProfileStateBuild(environment, this)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.build
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigTopLevelLineMarker
|
|
||||||
import com.falsepattern.zigbrains.zig.psi.ZigTypes
|
|
||||||
import com.intellij.icons.AllIcons.RunConfigurations.TestState
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.psi.util.elementType
|
|
||||||
import javax.swing.Icon
|
|
||||||
|
|
||||||
class ZigLineMarkerBuild: ZigTopLevelLineMarker() {
|
|
||||||
override fun getDeclaration(element: PsiElement): PsiElement? {
|
|
||||||
if (element.elementType != ZigTypes.IDENTIFIER)
|
|
||||||
return null
|
|
||||||
|
|
||||||
if (!element.textMatches("build"))
|
|
||||||
return null
|
|
||||||
|
|
||||||
val parent = element.parent ?: return null
|
|
||||||
if (parent.elementType != ZigTypes.FN_PROTO)
|
|
||||||
return null
|
|
||||||
|
|
||||||
val file = element.containingFile ?: return null
|
|
||||||
|
|
||||||
val fileName = file.virtualFile.name
|
|
||||||
if (fileName != "build.zig")
|
|
||||||
return null
|
|
||||||
|
|
||||||
return parent.parent
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getIcon(element: PsiElement): Icon {
|
|
||||||
return TestState.Run
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.build
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigProfileState
|
|
||||||
import com.intellij.execution.runners.ExecutionEnvironment
|
|
||||||
|
|
||||||
class ZigProfileStateBuild(environment: ExecutionEnvironment, configuration: ZigExecConfigBuild) : ZigProfileState<ZigExecConfigBuild>(environment, configuration)
|
|
|
@ -1,60 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.run
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigConfigProducer
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.findBuildZig
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.hasMainFunction
|
|
||||||
import com.falsepattern.zigbrains.project.execution.firstConfigFactory
|
|
||||||
import com.falsepattern.zigbrains.zig.psi.ZigFile
|
|
||||||
import com.intellij.execution.actions.ConfigurationFromContext
|
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
class ZigConfigProducerRun: ZigConfigProducer<ZigExecConfigRun>() {
|
|
||||||
override fun getConfigurationFactory(): ConfigurationFactory {
|
|
||||||
return firstConfigFactory<ZigConfigTypeRun>()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setupConfigurationFromContext(configuration: ZigExecConfigRun, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
|
|
||||||
if (!psiFile.hasMainFunction()) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (theFile.findBuildZig() != null) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
configuration.filePath.path = filePath
|
|
||||||
configuration.name = theFile.presentableName
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isConfigurationFromContext(configuration: ZigExecConfigRun, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
|
|
||||||
return filePath == configuration.filePath.path
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
|
|
||||||
return self.configurationType is ZigConfigTypeRun
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.run
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.Icons
|
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
|
||||||
import com.intellij.execution.configurations.ConfigurationTypeBase
|
|
||||||
import com.intellij.execution.configurations.RunConfiguration
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
|
|
||||||
class ZigConfigTypeRun : ConfigurationTypeBase(
|
|
||||||
IDENTIFIER,
|
|
||||||
ZigBrainsBundle.message("configuration.run.name"),
|
|
||||||
ZigBrainsBundle.message("configuration.run.description"),
|
|
||||||
Icons.Zig
|
|
||||||
) {
|
|
||||||
init {
|
|
||||||
addFactory(ConfigFactoryRun(this))
|
|
||||||
}
|
|
||||||
|
|
||||||
class ConfigFactoryRun(type: ZigConfigTypeRun): ConfigurationFactory(type) {
|
|
||||||
override fun createTemplateConfiguration(project: Project): RunConfiguration {
|
|
||||||
return ZigExecConfigRun(project, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getId(): String {
|
|
||||||
return IDENTIFIER
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private const val IDENTIFIER = "ZIGBRAINS_RUN"
|
|
|
@ -1,78 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.run
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.*
|
|
||||||
import com.intellij.execution.ExecutionException
|
|
||||||
import com.intellij.execution.Executor
|
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
|
||||||
import com.intellij.execution.runners.ExecutionEnvironment
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import kotlin.io.path.pathString
|
|
||||||
|
|
||||||
class ZigExecConfigRun(project: Project, factory: ConfigurationFactory): ZigExecConfig<ZigExecConfigRun>(project, factory, ZigBrainsBundle.message("exec.type.run.label")) {
|
|
||||||
var filePath = FilePathConfigurable("filePath", ZigBrainsBundle.message("exec.option.label.file-path"))
|
|
||||||
private set
|
|
||||||
var optimization = OptimizationConfigurable("optimization")
|
|
||||||
private set
|
|
||||||
var compilerArgs = ArgsConfigurable("compilerArgs", ZigBrainsBundle.message("exec.option.label.compiler-args"))
|
|
||||||
private set
|
|
||||||
var exeArgs = ArgsConfigurable("exeArgs", ZigBrainsBundle.message("exec.option.label.exe-args"))
|
|
||||||
private set
|
|
||||||
|
|
||||||
override suspend fun buildCommandLineArgs(debug: Boolean): List<String> {
|
|
||||||
val result = ArrayList<String>()
|
|
||||||
result.add(if (debug) "build-exe" else "run")
|
|
||||||
result.add(filePath.path?.pathString ?: throw ExecutionException(ZigBrainsBundle.message("exception.zig.empty-file-path")))
|
|
||||||
if (!debug || optimization.forced) {
|
|
||||||
result.addAll(listOf("-O", optimization.level.name))
|
|
||||||
}
|
|
||||||
result.addAll(compilerArgs.argsSplit())
|
|
||||||
if (!debug) {
|
|
||||||
result.add("--")
|
|
||||||
result.addAll(exeArgs.argsSplit())
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
override val suggestedName: String
|
|
||||||
get() = ZigBrainsBundle.message("configuration.run.suggested-name")
|
|
||||||
|
|
||||||
override fun clone(): ZigExecConfigRun {
|
|
||||||
val clone = super.clone()
|
|
||||||
clone.filePath = filePath.clone()
|
|
||||||
clone.compilerArgs = compilerArgs.clone()
|
|
||||||
clone.optimization = optimization.clone()
|
|
||||||
clone.exeArgs = exeArgs.clone()
|
|
||||||
return clone
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getConfigurables(): List<ZigConfigurable<*>> {
|
|
||||||
return super.getConfigurables() + listOf(filePath, optimization, compilerArgs, exeArgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getState(executor: Executor, environment: ExecutionEnvironment): ZigProfileState<ZigExecConfigRun> {
|
|
||||||
return ZigProfileStateRun(environment, this)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.run
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigTopLevelLineMarker
|
|
||||||
import com.falsepattern.zigbrains.zig.psi.ZigTypes
|
|
||||||
import com.intellij.icons.AllIcons.RunConfigurations.TestState
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.psi.util.elementType
|
|
||||||
import javax.swing.Icon
|
|
||||||
|
|
||||||
class ZigLineMarkerRun: ZigTopLevelLineMarker() {
|
|
||||||
override fun getDeclaration(element: PsiElement): PsiElement? {
|
|
||||||
if (element.elementType != ZigTypes.IDENTIFIER)
|
|
||||||
return null
|
|
||||||
|
|
||||||
if (!element.textMatches("main"))
|
|
||||||
return null
|
|
||||||
|
|
||||||
val parent = element.parent
|
|
||||||
if (parent.elementType != ZigTypes.FN_PROTO)
|
|
||||||
return null
|
|
||||||
|
|
||||||
return parent.parent
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getIcon(element: PsiElement): Icon {
|
|
||||||
return TestState.Run
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.run
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigProfileState
|
|
||||||
import com.intellij.execution.runners.ExecutionEnvironment
|
|
||||||
|
|
||||||
class ZigProfileStateRun(environment: ExecutionEnvironment, configuration: ZigExecConfigRun) : ZigProfileState<ZigExecConfigRun>(environment, configuration)
|
|
|
@ -1,61 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.test
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigConfigProducer
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.findBuildZig
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.hasTests
|
|
||||||
import com.falsepattern.zigbrains.project.execution.firstConfigFactory
|
|
||||||
import com.falsepattern.zigbrains.zig.psi.ZigFile
|
|
||||||
import com.intellij.execution.actions.ConfigurationFromContext
|
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
class ZigConfigProducerTest: ZigConfigProducer<ZigExecConfigTest>() {
|
|
||||||
override fun getConfigurationFactory(): ConfigurationFactory {
|
|
||||||
return firstConfigFactory<ZigConfigTypeTest>()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setupConfigurationFromContext(configuration: ZigExecConfigTest, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
|
|
||||||
if (!psiFile.hasTests()) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (theFile.findBuildZig() != null) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
configuration.filePath.path = filePath
|
|
||||||
configuration.name = ZigBrainsBundle.message("configuration.test.marker-name", theFile.presentableName)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isConfigurationFromContext(configuration: ZigExecConfigTest, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
|
|
||||||
return filePath == configuration.filePath.path
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
|
|
||||||
return self.configurationType is ZigConfigTypeTest
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.test
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.Icons
|
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
|
||||||
import com.intellij.execution.configurations.ConfigurationTypeBase
|
|
||||||
import com.intellij.execution.configurations.RunConfiguration
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
|
|
||||||
class ZigConfigTypeTest : ConfigurationTypeBase(
|
|
||||||
IDENTIFIER,
|
|
||||||
ZigBrainsBundle.message("configuration.test.name"),
|
|
||||||
ZigBrainsBundle.message("configuration.test.description"),
|
|
||||||
Icons.Zig
|
|
||||||
) {
|
|
||||||
init {
|
|
||||||
addFactory(ConfigFactoryRun(this))
|
|
||||||
}
|
|
||||||
|
|
||||||
class ConfigFactoryRun(type: ZigConfigTypeTest): ConfigurationFactory(type) {
|
|
||||||
override fun createTemplateConfiguration(project: Project): RunConfiguration {
|
|
||||||
return ZigExecConfigTest(project, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getId(): String {
|
|
||||||
return IDENTIFIER
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private const val IDENTIFIER = "ZIGBRAINS_TEST"
|
|
|
@ -1,75 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of ZigBrains.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2023-2025 FalsePattern
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included
|
|
||||||
* in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* ZigBrains is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, only version 3 of the License.
|
|
||||||
*
|
|
||||||
* ZigBrains is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.falsepattern.zigbrains.project.execution.test
|
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.*
|
|
||||||
import com.intellij.execution.ExecutionException
|
|
||||||
import com.intellij.execution.Executor
|
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
|
||||||
import com.intellij.execution.runners.ExecutionEnvironment
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import kotlin.io.path.pathString
|
|
||||||
|
|
||||||
class ZigExecConfigTest(project: Project, factory: ConfigurationFactory): ZigExecConfig<ZigExecConfigTest>(project, factory, ZigBrainsBundle.message("exec.type.test.label")) {
|
|
||||||
var filePath = FilePathConfigurable("filePath", ZigBrainsBundle.message("exec.option.label.file-path"))
|
|
||||||
private set
|
|
||||||
var optimization = OptimizationConfigurable("optimization")
|
|
||||||
private set
|
|
||||||
var compilerArgs = ArgsConfigurable("compilerArgs", ZigBrainsBundle.message("exec.option.label.compiler-args"))
|
|
||||||
private set
|
|
||||||
|
|
||||||
@Throws(ExecutionException::class)
|
|
||||||
override suspend fun buildCommandLineArgs(debug: Boolean): List<String> {
|
|
||||||
val result = ArrayList<String>()
|
|
||||||
result.add("test")
|
|
||||||
result.add(filePath.path?.pathString ?: throw ExecutionException(ZigBrainsBundle.message("exception.zig.empty-file-path")))
|
|
||||||
if (!debug || optimization.forced) {
|
|
||||||
result.addAll(listOf("-O", optimization.level.name))
|
|
||||||
}
|
|
||||||
result.addAll(compilerArgs.argsSplit())
|
|
||||||
if (debug) {
|
|
||||||
result.add("--test-no-exec")
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
override val suggestedName: String
|
|
||||||
get() = ZigBrainsBundle.message("configuration.test.suggested-name")
|
|
||||||
|
|
||||||
override fun clone(): ZigExecConfigTest {
|
|
||||||
val clone = super.clone()
|
|
||||||
clone.filePath = filePath.clone()
|
|
||||||
clone.compilerArgs = compilerArgs.clone()
|
|
||||||
clone.optimization = optimization.clone()
|
|
||||||
return clone
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getConfigurables(): List<ZigConfigurable<*>> {
|
|
||||||
return super.getConfigurables() + listOf(filePath, optimization, compilerArgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getState(executor: Executor, environment: ExecutionEnvironment): ZigProfileState<ZigExecConfigTest> {
|
|
||||||
return ZigProfileStateTest(environment, this)
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue