diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 000000000..354130a49
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,25 @@
+# IntelliJ Platform Artifacts Repositories -> https://plugins.jetbrains.com/docs/intellij/intellij-artifacts.html
+
+pluginGroup = me.devnatan.inventoryframework.tooling
+pluginName = Inventory Framework Tooling
+pluginRepositoryUrl = https://github.com/DevNatan/inventory-framework
+# SemVer format -> https://semver.org
+pluginVersion = 1.0.0
+
+# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
+pluginSinceBuild = 231
+pluginUntilBuild = 232.*
+
+# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
+platformType = IC
+platformVersion = 2023.2
+
+# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
+# Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22
+platformPlugins = com.intellij.java
+
+# Opt-out flag for bundling Kotlin standard library -> https://jb.gg/intellij-platform-kotlin-stdlib
+kotlin.stdlib.default.dependency = true
+
+# Enable Gradle Configuration Cache -> https://docs.gradle.org/current/userguide/configuration_cache.html
+org.gradle.unsafe.configuration-cache = true
diff --git a/inventory-framework-intellij-tooling/.github/ISSUE_TEMPLATE/bug_report.md b/inventory-framework-intellij-tooling/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 000000000..9821b18c8
--- /dev/null
+++ b/inventory-framework-intellij-tooling/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,23 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+---
+
+
+
+**Describe the bug:**
+
+
+**Steps to reproduce:**
+
+
+**Expected behavior:**
+
+
+**Additional context:**
+
diff --git a/inventory-framework-intellij-tooling/.github/dependabot.yml b/inventory-framework-intellij-tooling/.github/dependabot.yml
new file mode 100644
index 000000000..9be205f50
--- /dev/null
+++ b/inventory-framework-intellij-tooling/.github/dependabot.yml
@@ -0,0 +1,17 @@
+# Dependabot configuration:
+# https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/configuration-options-for-dependency-updates
+
+version: 2
+updates:
+ # Maintain dependencies for Gradle dependencies
+ - package-ecosystem: "gradle"
+ directory: "/"
+ target-branch: "next"
+ schedule:
+ interval: "daily"
+ # Maintain dependencies for GitHub Actions
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ target-branch: "next"
+ schedule:
+ interval: "daily"
diff --git a/inventory-framework-intellij-tooling/.github/template-cleanup/.github/dependabot.yml b/inventory-framework-intellij-tooling/.github/template-cleanup/.github/dependabot.yml
new file mode 100644
index 000000000..fe30e00de
--- /dev/null
+++ b/inventory-framework-intellij-tooling/.github/template-cleanup/.github/dependabot.yml
@@ -0,0 +1,15 @@
+# Dependabot configuration:
+# https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/configuration-options-for-dependency-updates
+
+version: 2
+updates:
+ # Maintain dependencies for Gradle dependencies
+ - package-ecosystem: "gradle"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ # Maintain dependencies for GitHub Actions
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "daily"
diff --git a/inventory-framework-intellij-tooling/.github/template-cleanup/CHANGELOG.md b/inventory-framework-intellij-tooling/.github/template-cleanup/CHANGELOG.md
new file mode 100644
index 000000000..619f92dd7
--- /dev/null
+++ b/inventory-framework-intellij-tooling/.github/template-cleanup/CHANGELOG.md
@@ -0,0 +1,7 @@
+
+
+# %NAME% Changelog
+
+## [Unreleased]
+### Added
+- Initial scaffold created from [IntelliJ Platform Plugin Template](https://github.com/JetBrains/intellij-platform-plugin-template)
diff --git a/inventory-framework-intellij-tooling/.github/template-cleanup/README.md b/inventory-framework-intellij-tooling/.github/template-cleanup/README.md
new file mode 100644
index 000000000..bc9ac8c24
--- /dev/null
+++ b/inventory-framework-intellij-tooling/.github/template-cleanup/README.md
@@ -0,0 +1,44 @@
+# %NAME%
+
+
+[](https://plugins.jetbrains.com/plugin/PLUGIN_ID)
+[](https://plugins.jetbrains.com/plugin/PLUGIN_ID)
+
+## Template ToDo list
+- [x] Create a new [IntelliJ Platform Plugin Template][template] project.
+- [ ] Get familiar with the [template documentation][template].
+- [ ] Adjust the [pluginGroup](gradle.properties), [plugin ID](./src/main/resources/META-INF/plugin.xml) and [sources package](./src/main/kotlin).
+- [ ] Adjust the plugin description in `README` (see [Tips][docs:plugin-description])
+- [ ] Review the [Legal Agreements](https://plugins.jetbrains.com/docs/marketplace/legal-agreements.html?from=IJPluginTemplate).
+- [ ] [Publish a plugin manually](https://plugins.jetbrains.com/docs/intellij/publishing-plugin.html?from=IJPluginTemplate) for the first time.
+- [ ] Set the `PLUGIN_ID` in the above README badges.
+- [ ] Set the [Plugin Signing](https://plugins.jetbrains.com/docs/intellij/plugin-signing.html?from=IJPluginTemplate) related [secrets](https://github.com/JetBrains/intellij-platform-plugin-template#environment-variables).
+- [ ] Set the [Deployment Token](https://plugins.jetbrains.com/docs/marketplace/plugin-upload.html?from=IJPluginTemplate).
+- [ ] Click the Watch button on the top of the [IntelliJ Platform Plugin Template][template] to be notified about releases containing new features and fixes.
+
+
+This Fancy IntelliJ Platform Plugin is going to be your implementation of the brilliant ideas that you have.
+
+This specific section is a source for the [plugin.xml](/src/main/resources/META-INF/plugin.xml) file which will be extracted by the [Gradle](/build.gradle.kts) during the build process.
+
+To keep everything working, do not remove `` sections.
+
+
+## Installation
+
+- Using IDE built-in plugin system:
+
+ Settings/Preferences > Plugins > Marketplace > Search for "%NAME%" >
+ Install Plugin
+
+- Manually:
+
+ Download the [latest release](https://github.com/%REPOSITORY%/releases/latest) and install it manually using
+ Settings/Preferences > Plugins > ⚙️ > Install plugin from disk...
+
+
+---
+Plugin based on the [IntelliJ Platform Plugin Template][template].
+
+[template]: https://github.com/JetBrains/intellij-platform-plugin-template
+[docs:plugin-description]: https://plugins.jetbrains.com/docs/intellij/plugin-user-experience.html#plugin-description-and-presentation
\ No newline at end of file
diff --git a/inventory-framework-intellij-tooling/.github/template-cleanup/gradle.properties b/inventory-framework-intellij-tooling/.github/template-cleanup/gradle.properties
new file mode 100644
index 000000000..b728ae7e2
--- /dev/null
+++ b/inventory-framework-intellij-tooling/.github/template-cleanup/gradle.properties
@@ -0,0 +1,30 @@
+# IntelliJ Platform Artifacts Repositories -> https://plugins.jetbrains.com/docs/intellij/intellij-artifacts.html
+
+pluginGroup = %GROUP%
+pluginName = %NAME%
+pluginRepositoryUrl = https://github.com/%REPOSITORY%
+# SemVer format -> https://semver.org
+pluginVersion = 0.0.1
+
+# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
+pluginSinceBuild = 221
+pluginUntilBuild = 231.*
+
+# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
+platformType = IC
+platformVersion = 2022.1.4
+
+# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
+# Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22
+platformPlugins =
+
+# Gradle Releases -> https://github.com/gradle/gradle/releases
+gradleVersion = 8.0.2
+
+# Opt-out flag for bundling Kotlin standard library -> https://jb.gg/intellij-platform-kotlin-stdlib
+# suppress inspection "UnusedProperty"
+kotlin.stdlib.default.dependency = false
+
+# Enable Gradle Configuration Cache -> https://docs.gradle.org/current/userguide/configuration_cache.html
+# suppress inspection "UnusedProperty"
+org.gradle.unsafe.configuration-cache = true
diff --git a/inventory-framework-intellij-tooling/.github/template-cleanup/settings.gradle.kts b/inventory-framework-intellij-tooling/.github/template-cleanup/settings.gradle.kts
new file mode 100644
index 000000000..34ec91d15
--- /dev/null
+++ b/inventory-framework-intellij-tooling/.github/template-cleanup/settings.gradle.kts
@@ -0,0 +1 @@
+rootProject.name = "%NAME%"
diff --git a/inventory-framework-intellij-tooling/.github/workflows/build.yml b/inventory-framework-intellij-tooling/.github/workflows/build.yml
new file mode 100644
index 000000000..4207647d4
--- /dev/null
+++ b/inventory-framework-intellij-tooling/.github/workflows/build.yml
@@ -0,0 +1,172 @@
+# GitHub Actions Workflow is created for testing and preparing the plugin release in the following steps:
+# - validate Gradle Wrapper,
+# - run 'test' and 'verifyPlugin' tasks,
+# - run Qodana inspections,
+# - run 'buildPlugin' task and prepare artifact for the further tests,
+# - run 'runPluginVerifier' task,
+# - create a draft release.
+#
+# Workflow is triggered on push and pull_request events.
+#
+# GitHub Actions reference: https://help.github.com/en/actions
+#
+## JBIJPPTPL
+
+name: Build
+on:
+ # Trigger the workflow on pushes to only the 'main' branch (this avoids duplicate checks being run e.g. for dependabot pull requests)
+ push:
+ branches: [main]
+ # Trigger the workflow on any pull request
+ pull_request:
+
+jobs:
+
+ # Run Gradle Wrapper Validation Action to verify the wrapper's checksum
+ # Run verifyPlugin, IntelliJ Plugin Verifier, and test Gradle tasks
+ # Build plugin and provide the artifact for the next workflow jobs
+ build:
+ name: Build
+ runs-on: ubuntu-latest
+ outputs:
+ version: ${{ steps.properties.outputs.version }}
+ changelog: ${{ steps.properties.outputs.changelog }}
+ steps:
+
+ # Free GitHub Actions Environment Disk Space
+ - name: Maximize Build Space
+ run: |
+ sudo rm -rf /usr/share/dotnet
+ sudo rm -rf /usr/local/lib/android
+ sudo rm -rf /opt/ghc
+
+ # Check out current repository
+ - name: Fetch Sources
+ uses: actions/checkout@v3
+
+ # Validate wrapper
+ - name: Gradle Wrapper Validation
+ uses: gradle/wrapper-validation-action@v1.0.6
+
+ # Setup Java 11 environment for the next steps
+ - name: Setup Java
+ uses: actions/setup-java@v3
+ with:
+ distribution: zulu
+ java-version: 11
+
+ # Set environment variables
+ - name: Export Properties
+ id: properties
+ shell: bash
+ run: |
+ PROPERTIES="$(./gradlew properties --console=plain -q)"
+ VERSION="$(echo "$PROPERTIES" | grep "^version:" | cut -f2- -d ' ')"
+ NAME="$(echo "$PROPERTIES" | grep "^pluginName:" | cut -f2- -d ' ')"
+ CHANGELOG="$(./gradlew getChangelog --unreleased --no-header --console=plain -q)"
+
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
+ echo "name=$NAME" >> $GITHUB_OUTPUT
+ echo "pluginVerifierHomeDir=~/.pluginVerifier" >> $GITHUB_OUTPUT
+
+ echo "changelog<> $GITHUB_OUTPUT
+ echo "$CHANGELOG" >> $GITHUB_OUTPUT
+ echo "EOF" >> $GITHUB_OUTPUT
+
+ ./gradlew listProductsReleases # prepare list of IDEs for Plugin Verifier
+
+ # Run tests
+ - name: Run Tests
+ run: ./gradlew check
+
+ # Collect Tests Result of failed tests
+ - name: Collect Tests Result
+ if: ${{ failure() }}
+ uses: actions/upload-artifact@v3
+ with:
+ name: tests-result
+ path: ${{ github.workspace }}/build/reports/tests
+
+ # Upload Kover report to CodeCov
+ - name: Upload Code Coverage Report
+ uses: codecov/codecov-action@v3
+ with:
+ files: ${{ github.workspace }}/build/reports/kover/xml/report.xml
+
+ # Cache Plugin Verifier IDEs
+ - name: Setup Plugin Verifier IDEs Cache
+ uses: actions/cache@v3
+ with:
+ path: ${{ steps.properties.outputs.pluginVerifierHomeDir }}/ides
+ key: plugin-verifier-${{ hashFiles('build/listProductsReleases.txt') }}
+
+ # Run Verify Plugin task and IntelliJ Plugin Verifier tool
+ - name: Run Plugin Verification tasks
+ run: ./gradlew runPluginVerifier -Dplugin.verifier.home.dir=${{ steps.properties.outputs.pluginVerifierHomeDir }}
+
+ # Collect Plugin Verifier Result
+ - name: Collect Plugin Verifier Result
+ if: ${{ always() }}
+ uses: actions/upload-artifact@v3
+ with:
+ name: pluginVerifier-result
+ path: ${{ github.workspace }}/build/reports/pluginVerifier
+
+ # Run Qodana inspections
+ - name: Qodana - Code Inspection
+ uses: JetBrains/qodana-action@v2022.3.4
+
+ # Prepare plugin archive content for creating artifact
+ - name: Prepare Plugin Artifact
+ id: artifact
+ shell: bash
+ run: |
+ cd ${{ github.workspace }}/build/distributions
+ FILENAME=`ls *.zip`
+ unzip "$FILENAME" -d content
+
+ echo "filename=${FILENAME:0:-4}" >> $GITHUB_OUTPUT
+
+ # Store already-built plugin as an artifact for downloading
+ - name: Upload artifact
+ uses: actions/upload-artifact@v3
+ with:
+ name: ${{ steps.artifact.outputs.filename }}
+ path: ./build/distributions/content/*/*
+
+ # Prepare a draft release for GitHub Releases page for the manual verification
+ # If accepted and published, release workflow would be triggered
+ releaseDraft:
+ name: Release Draft
+ if: github.event_name != 'pull_request'
+ needs: build
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+
+ # Check out current repository
+ - name: Fetch Sources
+ uses: actions/checkout@v3
+
+ # Remove old release drafts by using the curl request for the available releases with a draft flag
+ - name: Remove Old Release Drafts
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ gh api repos/{owner}/{repo}/releases \
+ --jq '.[] | select(.draft == true) | .id' \
+ | xargs -I '{}' gh api -X DELETE repos/{owner}/{repo}/releases/{}
+
+ # Create a new release draft which is not publicly visible and requires manual acceptance
+ - name: Create Release Draft
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ gh release create v${{ needs.build.outputs.version }} \
+ --draft \
+ --title "v${{ needs.build.outputs.version }}" \
+ --notes "$(cat << 'EOM'
+ ${{ needs.build.outputs.changelog }}
+ EOM
+ )"
diff --git a/inventory-framework-intellij-tooling/.github/workflows/release.yml b/inventory-framework-intellij-tooling/.github/workflows/release.yml
new file mode 100644
index 000000000..28395c886
--- /dev/null
+++ b/inventory-framework-intellij-tooling/.github/workflows/release.yml
@@ -0,0 +1,96 @@
+# GitHub Actions Workflow created for handling the release process based on the draft release prepared with the Build workflow.
+# Running the publishPlugin task requires all following secrets to be provided: PUBLISH_TOKEN, PRIVATE_KEY, PRIVATE_KEY_PASSWORD, CERTIFICATE_CHAIN.
+# See https://plugins.jetbrains.com/docs/intellij/plugin-signing.html for more information.
+
+name: Release
+on:
+ release:
+ types: [prereleased, released]
+
+jobs:
+
+ # Prepare and publish the plugin to the Marketplace repository
+ release:
+ name: Publish Plugin
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ pull-requests: write
+ steps:
+
+ # Check out current repository
+ - name: Fetch Sources
+ uses: actions/checkout@v3
+ with:
+ ref: ${{ github.event.release.tag_name }}
+
+ # Setup Java 11 environment for the next steps
+ - name: Setup Java
+ uses: actions/setup-java@v3
+ with:
+ distribution: zulu
+ java-version: 11
+
+ # Set environment variables
+ - name: Export Properties
+ id: properties
+ shell: bash
+ run: |
+ CHANGELOG="$(cat << 'EOM' | sed -e 's/^[[:space:]]*$//g' -e '/./,$!d'
+ ${{ github.event.release.body }}
+ EOM
+ )"
+
+ echo "changelog<> $GITHUB_OUTPUT
+ echo "$CHANGELOG" >> $GITHUB_OUTPUT
+ echo "EOF" >> $GITHUB_OUTPUT
+
+ # Update Unreleased section with the current release note
+ - name: Patch Changelog
+ if: ${{ steps.properties.outputs.changelog != '' }}
+ env:
+ CHANGELOG: ${{ steps.properties.outputs.changelog }}
+ run: |
+ ./gradlew patchChangelog --release-note="$CHANGELOG"
+
+ # Publish the plugin to the Marketplace
+ - name: Publish Plugin
+ env:
+ PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }}
+ CERTIFICATE_CHAIN: ${{ secrets.CERTIFICATE_CHAIN }}
+ PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
+ PRIVATE_KEY_PASSWORD: ${{ secrets.PRIVATE_KEY_PASSWORD }}
+ run: ./gradlew publishPlugin
+
+ # Upload artifact as a release asset
+ - name: Upload Release Asset
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: gh release upload ${{ github.event.release.tag_name }} ./build/distributions/*
+
+ # Create pull request
+ - name: Create Pull Request
+ if: ${{ steps.properties.outputs.changelog != '' }}
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ VERSION="${{ github.event.release.tag_name }}"
+ BRANCH="changelog-update-$VERSION"
+ LABEL="release changelog"
+
+ git config user.email "action@github.com"
+ git config user.name "GitHub Action"
+
+ git checkout -b $BRANCH
+ git commit -am "Changelog update - $VERSION"
+ git push --set-upstream origin $BRANCH
+
+ gh label create "$LABEL" \
+ --description "Pull requests with release changelog update" \
+ || true
+
+ gh pr create \
+ --title "Changelog update - \`$VERSION\`" \
+ --body "Current pull request contains patched \`CHANGELOG.md\` file for the \`$VERSION\` version." \
+ --label "$LABEL" \
+ --head $BRANCH
diff --git a/inventory-framework-intellij-tooling/.gitignore b/inventory-framework-intellij-tooling/.gitignore
new file mode 100644
index 000000000..e2e5d94ec
--- /dev/null
+++ b/inventory-framework-intellij-tooling/.gitignore
@@ -0,0 +1,4 @@
+.gradle
+.idea
+.qodana
+build
diff --git a/inventory-framework-intellij-tooling/CHANGELOG.md b/inventory-framework-intellij-tooling/CHANGELOG.md
new file mode 100644
index 000000000..2602fb097
--- /dev/null
+++ b/inventory-framework-intellij-tooling/CHANGELOG.md
@@ -0,0 +1,459 @@
+
+
+# IntelliJ Platform Plugin Template Changelog
+
+## [Unreleased]
+
+### Added
+- Migrate to Gradle Provider API improving configuration cache compatibility
+- Example code - `FrameStateListener` application listener
+- Example code - `MyToolWindowFactory` tool window basic implementation
+
+### Changed
+- Update `platformVersion` to `2022.1.4`
+- Change since/until build to `221-231.*` (2022.1 - 2023.1.*)
+- Example code - registered project service changed into a lightweight one
+- GitHub Actions - pass changelog release notes as a multi-line content
+- GitHub Actions - provide `plugin.verifier.home.dir` variable as a system property instead of project property
+- Template Cleanup: remove default `pluginIcon.svg` icon
+- Upgrade Gradle Wrapper to `8.0.2`
+- Dependencies - upgrade `org.jetbrains.kotlin.jvm` to `1.8.10`
+- Dependencies - upgrade `org.jetbrains.intellij` to `1.13.2`
+- Dependencies (GitHub Actions) - upgrade `JetBrains/qodana-action` to `v2022.3.4`
+- Dependencies (GitHub Actions) - upgrade `gradle/wrapper-validation-action` to `v1.0.6`
+
+### Fixed
+- Resolving the content for the `patchPluginXML.changeNotes` property
+
+### Removed
+- Example code - application service
+- Example code - deprecated `ProjectManagerListener` application listener
+
+## [1.4.0] - 2023-01-13
+
+### Changed
+- GitHub Actions - use `GITHUB_OUTPUT` environment file instead of `::set-output`.
+- Upgrade Gradle Wrapper to `7.6`
+- Dependencies - upgrade `org.jetbrains.kotlin.jvm` to `1.8.0`
+- Dependencies - upgrade `org.jetbrains.intellij` to `1.12.0`
+- Dependencies (GitHub Actions) - upgrade `JetBrains/qodana-action` to `v2022.3.0`
+
+### Fixed
+- Fallback to the unreleased change notes when the plugin in current was not released yet
+
+## [1.3.0] - 2022-11-17
+
+### Added
+- [Kover](https://github.com/Kotlin/kotlinx-kover) integration
+- Enable [Gradle Configuration Cache](https://docs.gradle.org/current/userguide/configuration_cache.html) in `gradle.proeprties`
+- GitHub Actions - mark the pull request created with _Publish Plugin_ workflow with `release changelog` label
+- GitHub Actions - send code coverage reports to [CodeCov](https://codecov.io)
+- Dependencies - upgrade `org.jetbrains.kotlinx.kover` to `0.6.1`
+
+### Changed
+- Update `changelog` extension configuration in `build.gradle.kts` file
+- Update `pluginUntilBuild` to include `223.*` (2022.3.*)
+- Use `kotlin.jvmToolchain(11)` shorthand in Gradle configuration
+- Dependencies - upgrade `org.jetbrains.intellij` to `1.10.0`
+- Dependencies - upgrade `org.jetbrains.changelog` to `2.0.0`
+- Dependencies - upgrade `org.jetbrains.kotlin.jvm` to `1.7.21`
+- Dependencies (GitHub Actions) - upgrade `JetBrains/qodana-action` to `v2022.2.3`
+- Dependencies (GitHub Actions) - upgrade `gradle/wrapper-validation-action` to `v1.0.5`
+- Dependencies (GitHub Actions) - upgrade `jtalk/url-health-check-action` to `v3`
+- Use `file` instead of `projectDir.resolve` in Gradle configuration file
+
+### Fixed
+- Update broken link in `gradle.properties`
+- GitHub Actions - use `$BRANCH` for creating changelog pull request
+
+## [1.2.0] - 2022-08-07
+
+### Added
+- Use JVM toolchain for configuring source/target compilation compatibility
+- Make sure GitHub Actions release jobs have write permissions
+- Example implementation: Add `TODO()` with a hint to remove stale sample code
+- Exclude `.qodana` directory from Qodana analysis
+- Maximize disk space on GitHub Actions
+
+### Changed
+- Upgrade Gradle Wrapper to `7.5.1`
+- Update `platformVersion` to `2021.3.3`
+- Change since/until build to `213-222.*` (2021.3 - 2022.2)
+- Dependencies - upgrade `org.jetbrains.intellij` to `1.8.0`
+- Dependencies - upgrade `org.jetbrains.kotlin.jvm` to `1.7.10`
+- Dependencies (GitHub Actions) - upgrade `actions/checkout` to `3`
+- Dependencies (GitHub Actions) - upgrade `actions/cache` to `3`
+- Dependencies (GitHub Actions) - upgrade `actions/setup-java` to `3`
+- Dependencies (GitHub Actions) - upgrade `actions/upload-artifact` to `3`
+- Dependencies (GitHub Actions) - upgrade `JetBrains/qodana-action` to `v2022.2.1`
+
+### Fixed
+- Pass Plugin Signing secrets as environment variables in the Release workflow
+
+### Removed
+- Removed Gradle caching from GitHub Actions
+
+## [1.1.2] - 2022-02-11
+
+### Changed
+- Update `platformVersion` to `2021.1.3` for compatibility with Apple M1
+- Change since/until build to `211-213.*` (2021.1 - 2021.3)
+- Upgrade Gradle Wrapper to `7.4`
+- Dependencies - upgrade `org.jetbrains.intellij` to `1.4.0`
+- Dependencies (GitHub Actions) - upgrade `JetBrains/qodana-action` to `4.2.5`
+
+## [1.1.1] - 2022-01-24
+
+### Changed
+- GitHub Actions - fixed duplicated `.zip` extension in artifact file's name of the build flow
+- Upgrade Gradle Wrapper to `7.3.3`
+- Dependencies - upgrade `org.jetbrains.intellij` to `1.3.1`
+- Dependencies - upgrade `org.jetbrains.kotlin.jvm` to `1.6.10`
+- Dependencies (GitHub Actions) - upgrade `JetBrains/qodana-action` to `4.2.3`
+- Dependencies (GitHub Actions) - upgrade `actions/cache` to `2.1.7`
+
+## [1.1.0] - 2021-11-16
+
+### Added
+- GitHub Actions: Collect Qodana/Tests/Plugin Verifier results as artifacts
+
+### Changed
+- Dependencies - upgrade `org.jetbrains.intellij` to `1.3.0`
+- Dependencies - upgrade `org.jetbrains.changelog` to `1.3.1`
+- Dependencies - upgrade `org.jetbrains.kotlin.jvm` to `1.6.0`
+- Dependencies (GitHub Actions) - upgrade `jtalk/url-health-check-action` to `2`
+- Dependencies (GitHub Actions) - upgrade `actions/checkout` to `2.3.5`
+- GitHub Actions general performance refactoring
+- GitHub Actions - prepare plugin archive content to be archived once
+- GitHub Actions - patch changelog only if change notes are provided
+- Update `pluginUntilBuild` to include `213.*` (2021.3.*)
+- Upgrade Gradle Wrapper to `7.3`
+
+### Fixed
+- Fixed passing change notes from `CHANGELOG.md` to the Release Draft
+- Fixed passing updated change notes from the Release Draft to `patchChangelog` Gradle task
+- Fixed `QODANA_SHOW_REPORT` environment variable resolving for Gradle `6.x`
+
+### Removed
+- Removed the `pluginVerifierIdeVersions` configuration to use default IDEs list provided by the `listProductsReleases` task for `runPluginVerifier`
+- Removed `platformDownloadSources` from Gradle configuration to use default value
+- Removed `updateSinceUntilBuild.set(true)` from Gradle configuration to use default value
+
+## [1.0.0] - 2021-09-07
+
+### Added
+- Plugin Signing
+- Qodana integration
+- Functional tests
+- Compatibility with Java 11
+- `Run Qodana` and `Run IDE for UI Tests` run configurations
+- Use Gradle `wrapper` task to handle Gradle updates
+- JVM compatibility version extracted to `gradle.properties` file
+- Suppress `UnusedProperty` inspection for the `kotlin.stdlib.default.dependency` in `gradle.properties`
+
+### Changed
+- GitHub Actions: Use Java 11
+- GitHub Actions: Update Build and Release flows
+- GitHub Actions: Use Gradle cache provided with `actions/setup-java`
+- Update `pluginVerifierIdeVersions` to `2020.3.4, 2021.1.3, 2021.2.1`
+- Change since/until build to `203-212.*`
+- Upgrade Gradle Wrapper to `7.2`
+- Gradle – Changelog plugin configuration update
+- Dependencies - upgrade `org.jetbrains.kotlin.jvm` to `1.5.30`
+- Dependencies - upgrade `org.jetbrains.changelog` to `1.3.0`
+- Dependencies - upgrade `org.jetbrains.intellij` to `1.1.6`
+- Dependencies (GitHub Actions) - upgrade `actions/upload-artifact` to `v2.2.4`
+
+### Fixed
+- Use `DynamicBundle` instead of `AbstractBundle` in `MyBundle.kt`
+
+### Removed
+- Removed `detekt`/`ktlint` integration
+
+## [0.10.1] - 2021-05-31
+
+### Added
+- Introduced `next` branch in the root repository to make `main` always a stable one
+
+### Changed
+- Dependencies (GitHub Actions) - upgrade `actions/cache` to `v2.1.6`
+- Trigger GitHub Actions `Build` workflows only on pushes to `main` branch or pull request to avoid duplicated checks
+
+## [0.10.0] - 2021-05-27
+
+### Changed
+- Remove reference to the `jcenter()` from Gradle configuration file
+- Update `pluginVerifierIdeVersions` to `2020.2.4, 2020.3.4, 2021.1.2`
+- Update `pluginUntilBuild` to include `211.*` (2021.1.*)
+- Dependencies - upgrade `org.jetbrains.kotlin.jvm` to `1.5.10`
+- Dependencies - upgrade `detekt-formatting from` to `1.17.1`
+- Dependencies - upgrade `io.gitlab.arturbosch.detekt` to `1.17.1`
+- Dependencies (GitHub Actions) - upgrade `actions/cache` to `v2.1.5`
+- Dependencies (GitHub Actions) - upgrade `actions/checkout` to `v2.3.4`
+- Dependencies (GitHub Actions) - upgrade `actions/upload-release-asset` to `v1.0.2`
+- Dependencies (GitHub Actions) - upgrade `actions/create-release` to `v1.1.4`
+- Upgrade Gradle Wrapper to `7.0.2`
+
+## [0.9.0] - 2021-03-29
+
+### Added
+- `properties` shorthand function for accessing `gradle.properties` in a cleaner way
+- Dependabot check for GitHub Actions used in [workflow files](.github/workflows)
+
+### Changed
+- Dependencies - upgrade `detekt-formatting from` to `1.16.0`
+- Dependencies - upgrade `io.gitlab.arturbosch.detekt` to `1.16.0`
+- Dependencies - upgrade `org.jetbrains.kotlin.jvm` to `1.4.32`
+- Dependencies (GitHub Actions) - upgrade `actions/upload-artifact` to `v2.2.2`
+- Dependencies (GitHub Actions) - upgrade `actions/cache` to `v2.1.4`
+
+### Fixed
+- Fix `README.md` file resolution in the `build.gradle.kts`
+
+## [0.8.3] - 2021-02-23
+
+### Changed
+- Dependencies - upgrade `org.jetbrains.intellij` to `0.7.2`
+- Dependencies - upgrade `org.jlleitschuh.gradle.ktlint` to `10.0.0`
+- Update `platformVersion` to `2020.2.4` for compatibility with macOS Big Sur
+- Upgrade Gradle Wrapper to `6.8.3`
+
+## [0.8.2] - 2021-02-09
+
+### Changed
+- Use `-bin` distribution of the Gradle Wrapper
+- Upgrade Gradle Wrapper to `6.8.2`
+- Update `pluginVerifierIdeVersions` in `gradle.properties` files
+- Dependencies - upgrade `org.jetbrains.kotlin.jvm` to `1.4.30`
+- Dependencies - upgrade `org.jetbrains.changelog` to `1.1.1`
+- Configure the `changelog` Gradle plugin
+
+## [0.8.1] - 2021-01-12
+
+### Added
+- README: Dependencies management section
+
+### Changed
+- Upgrade Gradle Wrapper to `6.8`
+- Dependencies - upgrade `org.jetbrains.changelog` to `1.0.0`
+
+### Fixed
+- Template Cleanup: Escape GitHub username to avoid incorrect characters in class package name
+- Template Cleanup: Run `ktlintFormat` task to fix imports order
+- GitHub Actions: Use the correct property in the "Upload artifact" step
+
+## [0.8.0] - 2020-12-21
+
+### Added
+- Dependabot integration
+- Show `idea.log` logs of the run IDE in the Run console
+- README: FAQ section
+
+### Changed
+- `build.gradle.kts`: simpler syntax for configuring `KotlinCompile`
+- Dependencies - upgrade `org.jetbrains.kotlin.jvm` to `1.4.21`
+- Dependencies - upgrade `detekt-formatting` to `1.15.0`
+- Dependencies - upgrade `io.gitlab.arturbosch.detekt` to `1.15.0`
+- README: Clarify the Java usage in the project
+- `pluginVerifierIdeVersions` - upgrade to `2020.1.4, 2020.2.3, 2020.3.1`
+
+### Fixed
+- Return `Supplier<@Nls String>` instead of `String` in `MyBundle.messagePointer`
+
+## [0.7.1] - 2020-12-02
+
+### Changed
+- Upgrade Gradle Wrapper to `6.7.1`
+- Dependencies - upgrade `org.jetbrains.intellij` to `0.6.5`
+- Dependencies - upgrade `org.jetbrains.kotlin.jvm` to `1.4.20`
+- Update the base platform version to 2020.1
+- Change since/until build to `201-203.*`
+
+## [0.7.0] - 2020-11-16
+
+### Added
+- Predefined Run/Debug Configurations
+- Project icon for development purposes
+
+### Changed
+- Dependencies - upgrade `org.jetbrains.intellij` to `0.6.3`
+
+## [0.6.1] - 2020-11-05
+
+### Added
+- GitHub Actions - use hash based on `pluginVerifierIdeVersions` in `Setup Plugin Verifier IDEs Cache` step
+
+### Changed
+- Use [Kotlin extension function](https://plugins.jetbrains.com/docs/intellij/plugin-services.html#retrieving-a-service) to retrieve the `MyProjectService` in the `MyProjectManagerListener`
+- Dependencies - upgrade `org.jetbrains.intellij` to `0.6.2`
+- Update `pluginVerifierIdeVersions` in the `gradle.properties` files
+
+## [0.6.0] - 2020-10-29
+
+### Added
+- Integration with [IntelliJ Plugin Verifier](https://github.com/JetBrains/intellij-plugin-verifier) through the [Gradle IntelliJ Plugin](https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#runpluginverifier-task) `runPluginVerifier` task
+- Cache downloaded IDEs used by Plugin Verifier for the verification
+
+### Changed
+- Switch Gradle Wrapper to `-all` to improve the IntelliSense
+- Update detekt config to be in line with IJ settings
+- Dependencies - upgrade `io.gitlab.arturbosch.detekt` to `1.14.2`
+- Dependencies - upgrade `org.jetbrains.intellij` to `0.6.1`
+- GitHub Actions - `gradleValidation` update to `gradle/wrapper-validation-action@v1.0.3`
+- GitHub Actions - `releaseDraft` update to `actions/download-artifact@v2`
+
+### Removed
+- Remove Third-party IntelliJ Plugin Verifier GitHub Action
+
+## [0.5.1] - 2020-10-15
+
+### Added
+- Missing properties in the `gradle.properties` template file
+
+### Changed
+- Upgrade Gradle Wrapper to `6.7`
+- Dependencies - upgrade `org.jetbrains.changelog` to `0.6.2`
+
+## [0.5.0] - 2020-10-12
+
+### Added
+- Introduced `platformPlugins` property in `gradle.properties` for configuring dependencies to bundled/external plugins
+
+### Changed
+- Disable "Release Draft" job for pull requests in the "Build" GitHub Actions Workflow
+- Dependencies - upgrade `org.jetbrains.intellij` to `0.5.0`
+- Dependencies - upgrade `org.jetbrains.changelog` to `0.6.1`
+- Dependencies - upgrade `io.gitlab.arturbosch.detekt` to `1.14.1`
+- Dependencies - upgrade `org.jlleitschuh.gradle.ktlint` to `9.4.1`
+- Remove LICENSE file during the Template Cleanup workflow
+
+## [0.4.0] - 2020-10-02
+
+### Added
+- Fix default to opt-out of bundling Kotlin standard library in plugin distribution
+
+### Changed
+- GitHub Actions: allow releasing plugin even for the base project
+- Dependencies - upgrade `org.jetbrains.kotlin.jvm` to `1.4.10`
+- Dependencies - upgrade `io.gitlab.arturbosch.detekt` to `1.13.1`
+
+### Fixed
+- `pluginName` variable name collision with `intellij` closure getter in Gradle configuration #29
+
+## [0.3.2] - 2020-08-09
+
+### Changed
+- Simplify and optimize GitHub Actions
+- Gradle Wrapper upgrade to `6.6.1`
+- Dependencies - upgrade `org.jetbrains.kotlin.jvm` to `1.4.0`
+- Dependencies - upgrade `org.jetbrains.intellij` to `0.4.22`
+- Dependencies - upgrade `org.jetbrains.changelog` to `0.5.0`
+- Dependencies - upgrade `io.gitlab.arturbosch.detekt` to `1.12.0`
+- Dependencies - upgrade `org.jlleitschuh.gradle.ktlint` to `9.4.0`
+- Rename `master` branch to `main`
+
+### Fixed
+- GitHub Actions - cache Gradle dependencies and wrapper separately
+
+## [0.3.1] - 2020-07-31
+
+### Added
+- Better handling of the Gradle plugin description extraction from the README file
+- GitHub Actions - cache Gradle Wrapper
+
+### Changed
+- Gradle - remove kotlin("stdlib-jdk8") dependency to decrease the plugin artifact size
+- Dependencies - bump ktlint to `9.3.0`
+- GitHub Actions - make *Update Changelog* job dependent on the *Publish Plugin*
+- GitHub Actions - run plugin verifier against `2019.3` `2020.1` `2020.2`
+
+### Fixed
+- Resolve ktlint reports
+- GitHub Actions - Plugin Verifier broken for artifacts with whitespaces in name
+
+## [0.3.0] - 2020-07-07
+
+### Added
+- Set publish channel depending on the plugin version, i.e. `1.0.0-beta` -> `beta` channel
+
+### Changed
+- Update `org.jetbrains.changelog` dependency to `v0.3.3`
+- Update Gradle Wrapper to `v6.5.1`
+- Run GitHub Actions Release workflow on `prereleased` event
+- GitHub Actions - Release - separate changelog related job from the release
+
+### Fixed
+- Remove vendor website from `plugin.xml`
+- Update Template Cleanup workflow test to avoid running it on forks
+
+## [0.2.0] - 2020-07-02
+
+### Added
+- JetBrains Plugin badges and TODO list for the end users
+- `ktlint` integration
+
+### Changed
+- `pluginUntilBuild` set to the correct format: `201.*`
+- Bump detekt dependency to `1.10.0`
+
+### Fixed
+- GitHub Actions - Template Cleanup - fixed adding files to git
+- Update Template plugin name on cleanup
+- Set `buildUponDefaultConfig = true` in detekt configuration
+
+## [0.1.0] - 2020-06-26
+
+### Added
+- `settings.gradle.kts` for the [performance purposes](https://docs.gradle.org/current/userguide/organizing_gradle_projects.html#always_define_a_settings_file)
+- `#REMOVE-ON-CLEANUP#` token to mark content to be removed with **Template Cleanup** workflow
+
+### Changed
+- README proofreading
+- GitHub Actions - Update IDE versions for the Plugin Verifier
+- Update platformVersion to `2020.1.2`
+
+## [0.0.2] - 2020-06-22
+
+### Added
+- [Gradle Changelog Plugin](https://github.com/JetBrains/gradle-changelog-plugin) integration
+
+### Changed
+- Bump Detekt version
+- Change pluginSinceBuild to 193
+
+## [0.0.1]
+
+### Added
+- Initial project scaffold
+- GitHub Actions to automate testing and deployment
+- Kotlin support
+
+[Unreleased]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v1.4.0...HEAD
+[1.4.0]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v1.3.0...v1.4.0
+[1.3.0]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v1.2.0...v1.3.0
+[1.2.0]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v1.1.2...v1.2.0
+[1.1.2]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v1.1.1...v1.1.2
+[1.1.1]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v1.1.0...v1.1.1
+[1.1.0]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v1.0.0...v1.1.0
+[1.0.0]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.10.1...v1.0.0
+[0.10.1]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.10.0...v0.10.1
+[0.10.0]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.9.0...v0.10.0
+[0.9.0]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.8.3...v0.9.0
+[0.8.3]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.8.2...v0.8.3
+[0.8.2]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.8.1...v0.8.2
+[0.8.1]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.8.0...v0.8.1
+[0.8.0]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.7.1...v0.8.0
+[0.7.1]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.7.0...v0.7.1
+[0.7.0]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.6.1...v0.7.0
+[0.6.1]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.6.0...v0.6.1
+[0.6.0]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.5.1...v0.6.0
+[0.5.1]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.5.0...v0.5.1
+[0.5.0]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.4.0...v0.5.0
+[0.4.0]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.3.2...v0.4.0
+[0.3.2]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.3.1...v0.3.2
+[0.3.1]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.3.0...v0.3.1
+[0.3.0]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.2.0...v0.3.0
+[0.2.0]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.1.0...v0.2.0
+[0.1.0]: https://github.com/JetBrains/intellij-platform-plugin-template/compare/v0.0.2...v0.1.0
+[0.0.2]: https://github.com/JetBrains/intellij-platform-plugin-template/commits/v0.0.2
+[0.0.1]: https://github.com/JetBrains/intellij-platform-plugin-template/commits
diff --git a/inventory-framework-intellij-tooling/CODE_OF_CONDUCT.md b/inventory-framework-intellij-tooling/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000..85ed20dba
--- /dev/null
+++ b/inventory-framework-intellij-tooling/CODE_OF_CONDUCT.md
@@ -0,0 +1,4 @@
+## Code of Conduct
+
+This project and the corresponding community is governed by the [JetBrains Open Source and Community Code of Conduct](https://confluence.jetbrains.com/display/ALL/JetBrains+Open+Source+and+Community+Code+of+Conduct). Please make sure you read it.
+
diff --git a/inventory-framework-intellij-tooling/LICENSE b/inventory-framework-intellij-tooling/LICENSE
new file mode 100644
index 000000000..77057df0f
--- /dev/null
+++ b/inventory-framework-intellij-tooling/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2000-2021 JetBrains s.r.o.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ 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.
diff --git a/inventory-framework-intellij-tooling/README.md b/inventory-framework-intellij-tooling/README.md
new file mode 100644
index 000000000..ed1220ebc
--- /dev/null
+++ b/inventory-framework-intellij-tooling/README.md
@@ -0,0 +1,5 @@
+# InventoryFramework IntelliJ Tooling
+
+
+Tooling support for Inventory Framework.
+
\ No newline at end of file
diff --git a/inventory-framework-intellij-tooling/build.gradle.kts b/inventory-framework-intellij-tooling/build.gradle.kts
new file mode 100644
index 000000000..4f484cac4
--- /dev/null
+++ b/inventory-framework-intellij-tooling/build.gradle.kts
@@ -0,0 +1,110 @@
+import org.jetbrains.changelog.Changelog
+import org.jetbrains.changelog.markdownToHTML
+
+fun properties(key: String): Provider = providers.gradleProperty(key)
+fun environment(key: String): Provider = providers.environmentVariable(key)
+
+plugins {
+ id("java")
+ id("org.jetbrains.kotlin.jvm") version "1.8.10"
+ id("org.jetbrains.intellij") version "1.13.2"
+ id("org.jetbrains.changelog") version "2.0.0"
+ id("org.jetbrains.qodana") version "0.1.13"
+ id("org.jetbrains.kotlinx.kover") version "0.6.1"
+}
+
+group = properties("pluginGroup").get()
+version = properties("pluginVersion").get()
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation(projects.inventoryFrameworkApi)
+}
+
+intellij {
+ pluginName.set(properties("pluginName"))
+ version.set(properties("platformVersion"))
+ type.set(properties("platformType"))
+
+ // Plugin Dependencies. Uses `platformPlugins` property from the gradle.properties file.
+ plugins.set(properties("platformPlugins")
+ .map { it.split(',')
+ .map(String::trim)
+ .filter(String::isNotEmpty)
+ })
+}
+
+changelog {
+ groups.empty()
+ repositoryUrl.set(properties("pluginRepositoryUrl"))
+}
+
+qodana {
+ cachePath.set(provider { file(".qodana").canonicalPath })
+ reportPath.set(provider { file("build/reports/inspections").canonicalPath })
+ saveReport.set(true)
+ showReport.set(environment("QODANA_SHOW_REPORT").map { it.toBoolean() }.getOrElse(false))
+}
+
+kover.xmlReport {
+ onCheck.set(true)
+}
+
+tasks {
+ patchPluginXml {
+ version.set(properties("pluginVersion"))
+ sinceBuild.set(properties("pluginSinceBuild"))
+ untilBuild.set(properties("pluginUntilBuild"))
+
+ pluginDescription.set(providers.fileContents(layout.projectDirectory.file("README.md")).asText.map {
+ val start = ""
+ val end = ""
+
+ with (it.lines()) {
+ if (!containsAll(listOf(start, end))) {
+ throw GradleException("Plugin description section not found in README.md:\n$start ... $end")
+ }
+ subList(indexOf(start) + 1, indexOf(end)).joinToString("\n").let(::markdownToHTML)
+ }
+ })
+
+ val changelog = project.changelog
+ changeNotes.set(properties("pluginVersion").map { pluginVersion ->
+ with(changelog) {
+ renderItem(
+ (getOrNull(pluginVersion) ?: getUnreleased())
+ .withHeader(false)
+ .withEmptySections(false),
+ Changelog.OutputType.HTML,
+ )
+ }
+ })
+ }
+
+ // Configure UI tests plugin
+ // Read more: https://github.com/JetBrains/intellij-ui-test-robot
+ runIdeForUiTests {
+ systemProperty("robot-server.port", "8082")
+ systemProperty("ide.mac.message.dialogs.as.sheets", "false")
+ systemProperty("jb.privacy.policy.text", "")
+ systemProperty("jb.consents.confirmation.enabled", "false")
+ }
+
+ signPlugin {
+ certificateChain.set(environment("CERTIFICATE_CHAIN"))
+ privateKey.set(environment("PRIVATE_KEY"))
+ password.set(environment("PRIVATE_KEY_PASSWORD"))
+ }
+
+ publishPlugin {
+ dependsOn("patchChangelog")
+ token.set(environment("PUBLISH_TOKEN"))
+ // The pluginVersion is based on the SemVer (https://semver.org) and supports pre-release labels, like 2.1.7-alpha.3
+ // Specify pre-release label to publish the plugin in a custom Release Channel automatically. Read more:
+ // https://plugins.jetbrains.com/docs/intellij/deployment.html#specifying-a-release-channel
+ channels.set(properties("pluginVersion").map { listOf(it.split('-').getOrElse(1) { "default" }.split('.').first()) })
+ }
+}
diff --git a/inventory-framework-intellij-tooling/qodana.yml b/inventory-framework-intellij-tooling/qodana.yml
new file mode 100644
index 000000000..d7c50656b
--- /dev/null
+++ b/inventory-framework-intellij-tooling/qodana.yml
@@ -0,0 +1,10 @@
+# Qodana configuration:
+# https://www.jetbrains.com/help/qodana/qodana-yaml.html
+
+version: 1.0
+profile:
+ name: qodana.recommended
+exclude:
+ - name: All
+ paths:
+ - .qodana
diff --git a/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/IFBundle.kt b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/IFBundle.kt
new file mode 100644
index 000000000..b6d947390
--- /dev/null
+++ b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/IFBundle.kt
@@ -0,0 +1,21 @@
+package me.devnatan.inventoryframework.tooling
+
+import com.intellij.DynamicBundle
+import org.jetbrains.annotations.NonNls
+import org.jetbrains.annotations.PropertyKey
+
+@NonNls
+private const val BUNDLE = "messages.InventoryFramework"
+
+object IFBundle : DynamicBundle(BUNDLE) {
+
+ @Suppress("SpreadOperator")
+ @JvmStatic
+ fun message(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any) =
+ getMessage(key, *params)
+
+ @Suppress("SpreadOperator", "unused")
+ @JvmStatic
+ fun messagePointer(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any) =
+ getLazyMessage(key, *params)
+}
diff --git a/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/IJResourceLoader.kt b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/IJResourceLoader.kt
new file mode 100644
index 000000000..5b106730d
--- /dev/null
+++ b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/IJResourceLoader.kt
@@ -0,0 +1,62 @@
+package me.devnatan.inventoryframework.tooling
+
+import io.github.classgraph.ClassGraph
+import java.io.File
+import java.io.IOException
+import java.io.InputStream
+import java.net.URL
+
+object IJResourceLoader {
+ var dir: String? = null
+
+ init {
+ if (Thread.currentThread().getContextClassLoader() == null) {
+ // without jar
+ dir = System.getProperty("user.dir")
+ if (dir == null) {
+ val currentDirFile = File(".")
+ val helper = currentDirFile.absolutePath
+ try {
+ dir = helper.substring(0, helper.length - currentDirFile.getCanonicalPath().length)
+ } catch (ignore: Exception) {
+ }
+ }
+ dir = File(dir, "resource").absolutePath
+ }
+ }
+
+ fun getResource(anyClassFromYouProject: Class<*>, filePath: String?): URL? {
+ if (dir != null) {
+ try {
+ return URL("file://" + File(dir, filePath).absolutePath)
+ } catch (ignore: Exception) {
+ }
+ }
+ var url: URL? = null
+ url = anyClassFromYouProject.getClassLoader().getResource(filePath)
+ if (url != null) {
+ return url
+ }
+ Thread.currentThread().setContextClassLoader(anyClassFromYouProject.getClassLoader())
+ url = Thread.currentThread().getContextClassLoader().getResource(filePath)
+ if (url != null) {
+ return url
+ }
+ val resources = ClassGraph().acceptPaths(filePath).scan().allResources
+ if (!resources.isEmpty()) {
+ resources[0].uri
+ }
+ return null
+ }
+
+ fun getResourceAsStream(anyClassFromYouProject: Class<*>, filePath: String?): InputStream? {
+ val url = getResource(anyClassFromYouProject, filePath)
+ if (url != null) {
+ try {
+ return url.openStream()
+ } catch (ignore: IOException) {
+ }
+ }
+ return null
+ }
+}
\ No newline at end of file
diff --git a/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/model/IFDeclaration.kt b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/model/IFDeclaration.kt
new file mode 100644
index 000000000..749e513e4
--- /dev/null
+++ b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/model/IFDeclaration.kt
@@ -0,0 +1,9 @@
+package me.devnatan.inventoryframework.tooling.model
+
+import me.devnatan.inventoryframework.ViewType
+
+data class IFDeclaration(
+ val title: String,
+ val lines: Int,
+ val type: ViewType,
+)
\ No newline at end of file
diff --git a/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/preview/PreviewComponent.kt b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/preview/PreviewComponent.kt
new file mode 100644
index 000000000..160bb200a
--- /dev/null
+++ b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/preview/PreviewComponent.kt
@@ -0,0 +1,129 @@
+package me.devnatan.inventoryframework.tooling.preview
+
+import com.intellij.openapi.fileEditor.FileDocumentManager
+import com.intellij.openapi.project.IndexNotReadyException
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiDocumentManager
+import com.intellij.psi.PsiJavaCodeReferenceElement
+import com.intellij.ui.AncestorListenerAdapter
+import com.intellij.ui.components.JBScrollPane
+import com.intellij.ui.dsl.builder.panel
+import me.devnatan.inventoryframework.tooling.IJResourceLoader
+import me.devnatan.inventoryframework.tooling.preview.ViewComponent.Companion.CHEST_SCALE
+import me.devnatan.inventoryframework.tooling.preview.ViewComponent.Companion.CHEST_WIDTH
+import me.devnatan.inventoryframework.tooling.psi.IF_VIEW_NAME_EXPR
+import java.awt.BorderLayout
+import java.awt.Dimension
+import java.awt.GridBagLayout
+import javax.imageio.ImageIO
+import javax.swing.ImageIcon
+import javax.swing.JComponent
+import javax.swing.JLabel
+import javax.swing.JLayeredPane
+import javax.swing.JPanel
+import javax.swing.ScrollPaneConstants
+import javax.swing.event.AncestorEvent
+
+class PreviewComponent(private val project: Project, file: VirtualFile) : JLayeredPane() {
+
+ private val doc = FileDocumentManager.getInstance().getDocument(file)!!
+
+ init {
+ layout = BorderLayout()
+ isVisible = true
+ minimumSize = Dimension(
+ CHEST_WIDTH * CHEST_SCALE + 10,
+ 0
+ )
+
+ addMouseWheelListener {
+ // DO NOTHING
+ }
+
+ redraw()
+ addAncestorListener(object: AncestorListenerAdapter() {
+ override fun ancestorMoved(event: AncestorEvent?) {
+ redraw()
+ }
+ })
+ }
+
+ fun redraw() {
+ val ui = this
+ if (!ui.isShowing) return
+
+ val tree = PsiDocumentManager.getInstance(project).getPsiFile(doc) ?: return
+
+ ui.removeAll()
+
+ val content = JBScrollPane(
+ panel {
+ row {
+ button("Rebuild") {
+ redraw()
+ }
+ }
+
+ for (el in tree.children) {
+ if (el !is PsiClass || el.isInterface) continue
+
+
+ try {
+ val child = el.extendsList?.children?.firstOrNull {
+ other -> other is PsiJavaCodeReferenceElement
+ } as? PsiJavaCodeReferenceElement ?: continue
+
+ if (!IF_VIEW_NAME_EXPR.matches(child.qualifiedName))
+ continue
+ } catch (_: IndexNotReadyException) { return@panel }
+
+ row {
+ label("COnfia no pai q vai da bão")
+ }
+ row("Preview") {
+ cell(JLabel(ImageIcon(ImageIO.read(IJResourceLoader.getResource(this::class.java, "sprites/chest-5.png")))))
+ }
+ }
+ },
+ ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
+ ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
+ )
+
+// ui.add(
+// JLabel("Currently this source code has no menu declaration!").centerComponent(),
+// BorderLayout.CENTER
+// )
+ ui.add(content)
+
+// val component = _component
+// if (component == null) {
+// ui.add(JPanel().apply {
+// layout = BoxLayout(this, BoxLayout.PAGE_AXIS)
+// border = EmptyBorder(10, 10, 0, 0)
+//
+// add(JLabel("Piroca de foice"), BorderLayout.CENTER)
+// })
+// }
+//
+// val panel = JPanel().apply {
+// layout = FlowLayout(FlowLayout.CENTER, 0, 0)
+// setBounds(
+// ui.width - (preferredSize.width + 20),
+// ui.height - (preferredSize.height + 50),
+// preferredSize.width,
+// preferredSize.height
+// )
+// }
+//// ui.setLayer(panel, 1)
+// ui.add(panel)
+// ui.validate()
+ }
+
+ private fun JComponent.centerComponent() = JPanel().apply {
+ isVisible = true
+ layout = GridBagLayout()
+ add(this@centerComponent)
+ }
+}
\ No newline at end of file
diff --git a/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/preview/PreviewFileEditor.kt b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/preview/PreviewFileEditor.kt
new file mode 100644
index 000000000..22d5ef44f
--- /dev/null
+++ b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/preview/PreviewFileEditor.kt
@@ -0,0 +1,45 @@
+package me.devnatan.inventoryframework.tooling.preview
+
+import com.intellij.openapi.fileEditor.FileEditor
+import com.intellij.openapi.fileEditor.FileEditorLocation
+import com.intellij.openapi.fileEditor.FileEditorState
+import com.intellij.openapi.fileEditor.TextEditor
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.util.UserDataHolderBase
+import com.intellij.openapi.vfs.VirtualFile
+import me.devnatan.inventoryframework.ViewType
+import me.devnatan.inventoryframework.tooling.model.IFDeclaration
+import java.beans.PropertyChangeListener
+import javax.swing.JComponent
+
+class PreviewFileEditor(project: Project, @JvmField val file: VirtualFile) : UserDataHolderBase(), FileEditor {
+
+ private val ui = PreviewComponent(project, file)
+
+ override fun getComponent(): JComponent = ui
+
+ override fun getPreferredFocusedComponent(): JComponent? = null
+
+ override fun getName(): String = "Inventory Framework Preview"
+
+ override fun setState(state: FileEditorState) {
+ }
+
+ override fun isModified() = false
+ override fun isValid() = true
+
+ override fun addPropertyChangeListener(listener: PropertyChangeListener) {
+ }
+
+ override fun removePropertyChangeListener(listener: PropertyChangeListener) {
+ }
+
+ override fun getCurrentLocation(): FileEditorLocation? = null
+
+ override fun dispose() {
+ }
+
+ override fun selectNotify() {
+ ui.redraw()
+ }
+}
\ No newline at end of file
diff --git a/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/preview/PreviewFileEditorProvider.kt b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/preview/PreviewFileEditorProvider.kt
new file mode 100644
index 000000000..0f15a0395
--- /dev/null
+++ b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/preview/PreviewFileEditorProvider.kt
@@ -0,0 +1,36 @@
+package me.devnatan.inventoryframework.tooling.preview
+
+import com.intellij.openapi.fileEditor.FileEditor
+import com.intellij.openapi.fileEditor.FileEditorPolicy
+import com.intellij.openapi.fileEditor.TextEditor
+import com.intellij.openapi.fileEditor.TextEditorWithPreview
+import com.intellij.openapi.fileEditor.WeighedFileEditorProvider
+import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.vfs.VirtualFile
+
+class PreviewFileEditorProvider : WeighedFileEditorProvider() {
+
+ companion object {
+ private const val EDITOR_ID = "inventory-framework-preview"
+ private const val EDITOR_NAME = "Inventory Framework"
+ }
+
+ override fun accept(project: Project, file: VirtualFile): Boolean {
+ return file.nameWithoutExtension.endsWith("View")
+ }
+
+ override fun createEditor(project: Project, file: VirtualFile): FileEditor {
+ return TextEditorWithPreview(
+ /* editor = */ TextEditorProvider.getInstance().createEditor(project, file) as TextEditor,
+ /* preview = */ PreviewFileEditor(project, file),
+ /* editorName = */ EDITOR_NAME
+ )
+ }
+
+ override fun getEditorTypeId(): String {
+ return EDITOR_ID
+ }
+
+ override fun getPolicy(): FileEditorPolicy = FileEditorPolicy.HIDE_DEFAULT_EDITOR
+}
\ No newline at end of file
diff --git a/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/preview/RebuildTask.kt b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/preview/RebuildTask.kt
new file mode 100644
index 000000000..385201b2f
--- /dev/null
+++ b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/preview/RebuildTask.kt
@@ -0,0 +1,76 @@
+package me.devnatan.inventoryframework.tooling.preview
+
+import com.intellij.openapi.module.ModuleManager
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.vfs.VirtualFileManager
+import com.intellij.openapi.vfs.newvfs.BulkFileListener
+import com.intellij.openapi.vfs.newvfs.events.VFileEvent
+import com.intellij.task.ProjectTaskManager
+import kotlinx.datetime.Clock
+
+class RebuildTask(val project: Project) {
+
+ private val rebuildStart = mutableListOf<() -> Unit>()
+ private val rebuildFinish = mutableListOf<() -> Unit>()
+ private val projectTaskManager = ProjectTaskManager.getInstance(project)
+
+ private var lastRebuild = Clock.System.now()
+
+ var rebuildInProgress = false
+ private set
+ private var shouldRebuild = false
+
+ init {
+ with(project.messageBus.connect()) {
+ subscribe(VirtualFileManager.VFS_CHANGES, object : BulkFileListener {
+ override fun after(events: List) {
+ run()
+ }
+ })
+ }
+ }
+
+ fun onRebuildStart(rebuild: () -> Unit) {
+ rebuildStart.add(rebuild);
+ }
+
+ fun onRebuildFinish(rebuild: () -> Unit) {
+ rebuildFinish.add(rebuild)
+ }
+
+ fun run(reschedule: Boolean = true) {
+ val now = Clock.System.now()
+ if ((now - lastRebuild).inWholeMilliseconds < 100)
+ return
+
+ lastRebuild = now
+ if (rebuildInProgress) {
+ shouldRebuild = reschedule
+ return
+ }
+
+ rebuildInProgress = true
+ rebuildStart.forEach { it() }
+ val buildTask = projectTaskManager.createModulesBuildTask(
+ /* modules = */ ModuleManager.getInstance(project).modules,
+ /* isIncrementalBuild = */ true,
+ /* includeDependentModules = */ false,
+ /* includeRuntimeDependencies = */ false,
+ /* includeTests = */ false
+ )
+ projectTaskManager
+ .run(buildTask)
+ .onError {
+ rebuildInProgress = false
+ shouldRebuild = false
+ }.onSuccess {
+ rebuildInProgress = false
+ rebuildFinish.forEach { it() }
+
+ if (shouldRebuild) {
+ shouldRebuild = false
+ run()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/preview/ViewComponent.kt b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/preview/ViewComponent.kt
new file mode 100644
index 000000000..53d791ba5
--- /dev/null
+++ b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/preview/ViewComponent.kt
@@ -0,0 +1,36 @@
+package me.devnatan.inventoryframework.tooling.preview
+
+import com.intellij.ui.JBColor
+import com.intellij.util.ImageLoader
+import com.intellij.util.ui.ImageUtil
+import me.devnatan.inventoryframework.tooling.model.IFDeclaration
+import java.awt.Dimension
+import java.awt.Graphics
+import java.awt.Graphics2D
+import java.awt.GridBagLayout
+import java.awt.Image
+import java.awt.image.BufferedImage
+import javax.swing.JPanel
+
+class ViewComponent(private val declaration: IFDeclaration) : JPanel() {
+
+ companion object {
+ const val CHEST_SCALE = 2
+ const val CHEST_SINGLE_LINE_HEIGHT = 42
+ const val CHEST_LINE_DIFF = 18
+ const val CHEST_WIDTH = 176
+ }
+
+ private val image: Image = ImageLoader.loadFromResource("/assets/sprites/chest-${declaration.lines}.png", this::class.java)!!
+
+ override fun paintComponent(g: Graphics) {
+ super.paintComponent(g)
+ g.drawImage(image, 0, 0, this)
+ }
+
+ private fun calculateDimension(): Dimension {
+ val height = CHEST_SINGLE_LINE_HEIGHT + (declaration.lines - 1) * CHEST_LINE_DIFF
+ return Dimension((CHEST_WIDTH * CHEST_SCALE), (height * CHEST_SCALE))
+ }
+
+}
\ No newline at end of file
diff --git a/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/psi/findViewDeclaration.kt b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/psi/findViewDeclaration.kt
new file mode 100644
index 000000000..b5454d29d
--- /dev/null
+++ b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/psi/findViewDeclaration.kt
@@ -0,0 +1,21 @@
+package me.devnatan.inventoryframework.tooling.psi
+
+import com.intellij.psi.PsiElement
+import me.devnatan.inventoryframework.ViewType
+import me.devnatan.inventoryframework.tooling.model.IFDeclaration
+import me.devnatan.inventoryframework.tooling.preview.ViewComponent
+
+val IF_VIEW_NAME_EXPR = Regex("me.devnatan.inventoryframework.([-a-zA-Z]*)View")
+
+fun elementToDeclaration(element: PsiElement): IFDeclaration {
+ return IFDeclaration(
+ title = "Macaco lol",
+ lines = 5,
+ type = ViewType.CHEST,
+ )
+}
+
+fun elementToComponent(element: PsiElement): ViewComponent {
+ val declaration = elementToDeclaration(element)
+ return ViewComponent(declaration)
+}
\ No newline at end of file
diff --git a/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/services/MyProjectService.kt b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/services/MyProjectService.kt
new file mode 100644
index 000000000..452dfec5e
--- /dev/null
+++ b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/services/MyProjectService.kt
@@ -0,0 +1,12 @@
+package me.devnatan.inventoryframework.tooling.services
+
+import com.intellij.openapi.components.Service
+import com.intellij.openapi.diagnostic.thisLogger
+import com.intellij.openapi.project.Project
+import me.devnatan.inventoryframework.tooling.IFBundle
+
+@Service(Service.Level.PROJECT)
+class MyProjectService(project: Project) {
+
+ fun getRandomNumber() = (1..100).random()
+}
diff --git a/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/toolWindow/MyToolWindowFactory.kt b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/toolWindow/MyToolWindowFactory.kt
new file mode 100644
index 000000000..db56d9a69
--- /dev/null
+++ b/inventory-framework-intellij-tooling/src/main/kotlin/me/devnatan/inventoryframework/tooling/toolWindow/MyToolWindowFactory.kt
@@ -0,0 +1,47 @@
+package me.devnatan.inventoryframework.tooling.toolWindow
+
+import com.intellij.openapi.components.service
+import com.intellij.openapi.diagnostic.thisLogger
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.wm.ToolWindow
+import com.intellij.openapi.wm.ToolWindowFactory
+import com.intellij.ui.components.JBLabel
+import com.intellij.ui.components.JBPanel
+import com.intellij.ui.content.ContentFactory
+import me.devnatan.inventoryframework.tooling.IFBundle
+import me.devnatan.inventoryframework.tooling.services.MyProjectService
+import javax.swing.JButton
+
+
+class MyToolWindowFactory : ToolWindowFactory {
+
+ init {
+ thisLogger().warn("Don't forget to remove all non-needed sample code files with their corresponding registration entries in `plugin.xml`.")
+ }
+
+ private val contentFactory = ContentFactory.SERVICE.getInstance()
+
+ override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
+ val myToolWindow = MyToolWindow(toolWindow)
+ val content = contentFactory.createContent(myToolWindow.getContent(), null, false)
+ toolWindow.contentManager.addContent(content)
+ }
+
+ override fun shouldBeAvailable(project: Project) = true
+
+ class MyToolWindow(toolWindow: ToolWindow) {
+
+ private val service = toolWindow.project.service()
+
+ fun getContent() = JBPanel>().apply {
+ val label = JBLabel(IFBundle.message("randomLabel", "?"))
+
+ add(label)
+ add(JButton(IFBundle.message("shuffle")).apply {
+ addActionListener {
+ label.text = IFBundle.message("randomLabel", service.getRandomNumber())
+ }
+ })
+ }
+ }
+}
diff --git a/inventory-framework-intellij-tooling/src/main/resources/META-INF/plugin.xml b/inventory-framework-intellij-tooling/src/main/resources/META-INF/plugin.xml
new file mode 100644
index 000000000..32ed12fb0
--- /dev/null
+++ b/inventory-framework-intellij-tooling/src/main/resources/META-INF/plugin.xml
@@ -0,0 +1,14 @@
+
+
+ me.devnatan.inventoryframework.tooling
+ Inventory Framework Tooling Plugin
+ DevNatan
+ com.intellij.modules.platform
+ com.intellij.modules.lang
+ com.intellij.modules.java
+ messages.InventoryFramework
+
+
+
+
diff --git a/inventory-framework-intellij-tooling/src/main/resources/META-INF/pluginIcon.svg b/inventory-framework-intellij-tooling/src/main/resources/META-INF/pluginIcon.svg
new file mode 100644
index 000000000..af611a580
--- /dev/null
+++ b/inventory-framework-intellij-tooling/src/main/resources/META-INF/pluginIcon.svg
@@ -0,0 +1,11 @@
+
diff --git a/inventory-framework-intellij-tooling/src/main/resources/messages/InventoryFramework.properties b/inventory-framework-intellij-tooling/src/main/resources/messages/InventoryFramework.properties
new file mode 100644
index 000000000..5669b75c0
--- /dev/null
+++ b/inventory-framework-intellij-tooling/src/main/resources/messages/InventoryFramework.properties
@@ -0,0 +1,4 @@
+name=Inventory Framework
+projectService=Project service: {0}
+randomLabel=The random number is: {0}
+shuffle=Shuffle
diff --git a/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-1.png b/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-1.png
new file mode 100644
index 000000000..9e4b5e557
Binary files /dev/null and b/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-1.png differ
diff --git a/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-2.png b/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-2.png
new file mode 100644
index 000000000..d805a74be
Binary files /dev/null and b/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-2.png differ
diff --git a/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-3.png b/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-3.png
new file mode 100644
index 000000000..9a75060b2
Binary files /dev/null and b/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-3.png differ
diff --git a/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-4.png b/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-4.png
new file mode 100644
index 000000000..1d3bf1e34
Binary files /dev/null and b/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-4.png differ
diff --git a/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-5.png b/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-5.png
new file mode 100644
index 000000000..6da9123bb
Binary files /dev/null and b/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-5.png differ
diff --git a/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-6.png b/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-6.png
new file mode 100644
index 000000000..fb20d24f9
Binary files /dev/null and b/inventory-framework-intellij-tooling/src/main/resources/resource/sprites/chest-6.png differ
diff --git a/settings.gradle b/settings.gradle
index 907d54e75..8ee887084 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -6,4 +6,5 @@ include 'inventory-framework-test',
'inventory-framework-core',
'inventory-framework-platform',
'inventory-framework-platform-paper',
- 'inventory-framework-platform-bukkit'
+ 'inventory-framework-platform-bukkit',
+ 'inventory-framework-intellij-tooling'
\ No newline at end of file