@ -1,23 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
<!-- Please do not use this issue tracker for support or questions, use Forum or Slack listed here:
|
||||
https://plugins.jetbrains.com/docs/intellij/getting-help.html
|
||||
Please **always** provide link to sources if possible. -->
|
||||
|
||||
**Describe the bug:**
|
||||
<!-- A clear and concise description of what the bug is. -->
|
||||
|
||||
**Steps to reproduce:**
|
||||
<!-- Steps to reproduce the issue. -->
|
||||
|
||||
**Expected behavior:**
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
**Additional context:**
|
||||
<!-- Add any other context about the problem here. -->
|
@ -1,17 +0,0 @@
|
||||
# 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"
|
Before Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 177 KiB |
Before Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 123 KiB |
Before Width: | Height: | Size: 264 KiB |
Before Width: | Height: | Size: 361 KiB |
Before Width: | Height: | Size: 175 KiB |
@ -1,15 +0,0 @@
|
||||
# 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"
|
@ -1,7 +0,0 @@
|
||||
<!-- Keep a Changelog guide -> https://keepachangelog.com -->
|
||||
|
||||
# %NAME% Changelog
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- Initial scaffold created from [IntelliJ Platform Plugin Template](https://github.com/JetBrains/intellij-platform-plugin-template)
|
@ -1,44 +0,0 @@
|
||||
# %NAME%
|
||||
|
||||
![Build](https://github.com/%REPOSITORY%/workflows/Build/badge.svg)
|
||||
[![Version](https://img.shields.io/jetbrains/plugin/v/PLUGIN_ID.svg)](https://plugins.jetbrains.com/plugin/PLUGIN_ID)
|
||||
[![Downloads](https://img.shields.io/jetbrains/plugin/d/PLUGIN_ID.svg)](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 <kbd>Watch</kbd> button on the top of the [IntelliJ Platform Plugin Template][template] to be notified about releases containing new features and fixes.
|
||||
|
||||
<!-- Plugin description -->
|
||||
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.
|
||||
<!-- Plugin description end -->
|
||||
|
||||
## Installation
|
||||
|
||||
- Using IDE built-in plugin system:
|
||||
|
||||
<kbd>Settings/Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>Marketplace</kbd> > <kbd>Search for "%NAME%"</kbd> >
|
||||
<kbd>Install Plugin</kbd>
|
||||
|
||||
- Manually:
|
||||
|
||||
Download the [latest release](https://github.com/%REPOSITORY%/releases/latest) and install it manually using
|
||||
<kbd>Settings/Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>⚙️</kbd> > <kbd>Install plugin from disk...</kbd>
|
||||
|
||||
|
||||
---
|
||||
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
|
@ -1,37 +0,0 @@
|
||||
# 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 = 222
|
||||
pluginUntilBuild = 232.*
|
||||
|
||||
# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
|
||||
platformType = IC
|
||||
platformVersion = 2022.2.5
|
||||
|
||||
# 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.1.1
|
||||
|
||||
# Opt-out flag for bundling Kotlin standard library -> https://jb.gg/intellij-platform-kotlin-stdlib
|
||||
kotlin.stdlib.default.dependency = false
|
||||
|
||||
# Enable Gradle Configuration Cache -> https://docs.gradle.org/current/userguide/configuration_cache.html
|
||||
org.gradle.configuration-cache = true
|
||||
|
||||
# Enable Gradle Build Cache -> https://docs.gradle.org/current/userguide/build_cache.html
|
||||
org.gradle.caching = true
|
||||
|
||||
# Enable Gradle Kotlin DSL Lazy Property Assignment -> https://docs.gradle.org/current/userguide/kotlin_dsl.html#kotdsl:assignment
|
||||
systemProp.org.gradle.unsafe.kotlin.assignment = true
|
||||
|
||||
# Temporary workaround for Kotlin Compiler OutOfMemoryError -> https://jb.gg/intellij-platform-kotlin-oom
|
||||
kotlin.incremental.useClasspathSnapshot = false
|
@ -1 +0,0 @@
|
||||
rootProject.name = "%NAME%"
|
@ -1,173 +0,0 @@
|
||||
# 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 environment for the next steps
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: zulu
|
||||
java-version: 17
|
||||
cache: gradle
|
||||
|
||||
# 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<<EOF" >> $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@v2023.1.0
|
||||
|
||||
# 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
|
||||
)"
|
@ -1,97 +0,0 @@
|
||||
# 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 environment for the next steps
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: zulu
|
||||
java-version: 17
|
||||
cache: gradle
|
||||
|
||||
# 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<<EOF" >> $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
|
@ -1,60 +0,0 @@
|
||||
# GitHub Actions Workflow for launching UI tests on Linux, Windows, and Mac in the following steps:
|
||||
# - prepare and launch IDE with your plugin and robot-server plugin, which is needed to interact with UI
|
||||
# - wait for IDE to start
|
||||
# - run UI tests with separate Gradle task
|
||||
#
|
||||
# Please check https://github.com/JetBrains/intellij-ui-test-robot for information about UI tests with IntelliJ Platform
|
||||
#
|
||||
# Workflow is triggered manually.
|
||||
|
||||
name: Run UI Tests
|
||||
on:
|
||||
workflow_dispatch
|
||||
|
||||
jobs:
|
||||
|
||||
testUI:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
runIde: |
|
||||
export DISPLAY=:99.0
|
||||
Xvfb -ac :99 -screen 0 1920x1080x16 &
|
||||
gradle runIdeForUiTests &
|
||||
- os: windows-latest
|
||||
runIde: start gradlew.bat runIdeForUiTests
|
||||
- os: macos-latest
|
||||
runIde: ./gradlew runIdeForUiTests &
|
||||
|
||||
steps:
|
||||
|
||||
# Check out current repository
|
||||
- name: Fetch Sources
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Setup Java environment for the next steps
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: zulu
|
||||
java-version: 17
|
||||
cache: gradle
|
||||
|
||||
# Run IDEA prepared for UI testing
|
||||
- name: Run IDE
|
||||
run: ${{ matrix.runIde }}
|
||||
|
||||
# Wait for IDEA to be started
|
||||
- name: Health Check
|
||||
uses: jtalk/url-health-check-action@v3
|
||||
with:
|
||||
url: http://127.0.0.1:8082
|
||||
max-attempts: 15
|
||||
retry-delay: 30s
|
||||
|
||||
# Run tests
|
||||
- name: Tests
|
||||
run: ./gradlew test
|
@ -1,82 +0,0 @@
|
||||
# GitHub Actions Workflow responsible for cleaning up the IntelliJ Platform Plugin Template repository from
|
||||
# the template-specific files and configurations. This workflow is supposed to be triggered automatically
|
||||
# when a new template-based repository has been created.
|
||||
|
||||
name: Template Cleanup
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
|
||||
# Run a cleaning process only if the workflow is triggered by the non-"intellij-platform-plugin-template" repository.
|
||||
template-cleanup:
|
||||
name: Template Cleanup
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.repository.name != 'intellij-platform-plugin-template'
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
|
||||
# Check out current repository
|
||||
- name: Fetch Sources
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Cleanup project
|
||||
- name: Cleanup
|
||||
run: |
|
||||
export LC_CTYPE=C
|
||||
export LANG=C
|
||||
|
||||
# Prepare variables
|
||||
NAME="${GITHUB_REPOSITORY##*/}"
|
||||
ACTOR=$(echo $GITHUB_ACTOR | tr '[:upper:]' '[:lower:]')
|
||||
SAFE_NAME=$(echo $NAME | sed 's/[^a-zA-Z0-9]//g' | tr '[:upper:]' '[:lower:]')
|
||||
SAFE_ACTOR=$(echo $ACTOR | sed 's/[^a-zA-Z0-9]//g' | tr '[:upper:]' '[:lower:]')
|
||||
GROUP="com.github.$SAFE_ACTOR.$SAFE_NAME"
|
||||
|
||||
# Replace placeholders in the template-cleanup files
|
||||
sed -i "s/%NAME%/$NAME/g" .github/template-cleanup/*
|
||||
sed -i "s/%REPOSITORY%/${GITHUB_REPOSITORY/\//\\/}/g" .github/template-cleanup/*
|
||||
sed -i "s/%GROUP%/$GROUP/g" .github/template-cleanup/*
|
||||
|
||||
# Replace template package name in project files with $GROUP
|
||||
find src -type f -exec sed -i "s/org.jetbrains.plugins.template/$GROUP/g" {} +
|
||||
find src -type f -exec sed -i "s/IntelliJ Platform Plugin/$NAME/g" {} +
|
||||
find src -type f -exec sed -i "s/JetBrains/$ACTOR/g" {} +
|
||||
|
||||
# Move content
|
||||
mkdir -p src/main/kotlin/${GROUP//.//}
|
||||
mkdir -p src/test/kotlin/${GROUP//.//}
|
||||
cp -R .github/template-cleanup/* .
|
||||
cp -R src/main/kotlin/org/jetbrains/plugins/template/* src/main/kotlin/${GROUP//.//}/
|
||||
cp -R src/test/kotlin/org/jetbrains/plugins/template/* src/test/kotlin/${GROUP//.//}/
|
||||
|
||||
# Cleanup
|
||||
rm -rf \
|
||||
.github/ISSUE_TEMPLATE \
|
||||
.github/readme \
|
||||
.github/template-cleanup \
|
||||
.github/workflows/template-cleanup.yml \
|
||||
.github/workflows/template-verify.yml \
|
||||
.idea/icon.png \
|
||||
src/main/kotlin/org \
|
||||
src/test/kotlin/org \
|
||||
src/main/resources/META-INF/pluginIcon.svg \
|
||||
CODE_OF_CONDUCT.md \
|
||||
LICENSE
|
||||
|
||||
# Commit modified files
|
||||
- name: Commit files
|
||||
run: |
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "GitHub Action"
|
||||
git add .
|
||||
git commit -m "Template cleanup"
|
||||
|
||||
# Push changes
|
||||
- name: Push changes
|
||||
uses: ad-m/github-push-action@master
|
||||
with:
|
||||
branch: main
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
@ -1,43 +0,0 @@
|
||||
# GitHub Actions Workflow verifies if the template repository is consistent with all provided content.
|
||||
|
||||
name: Template Verify
|
||||
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]
|
||||
paths: ['**/gradle.properties']
|
||||
# Trigger the workflow on any pull request
|
||||
pull_request:
|
||||
paths: ['**/gradle.properties']
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
name: Template Verify
|
||||
if: github.event.repository.name == 'intellij-platform-plugin-template'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.properties.outputs.version }}
|
||||
changelog: ${{ steps.properties.outputs.changelog }}
|
||||
steps:
|
||||
|
||||
# Check out current repository
|
||||
- name: Fetch Sources
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Compare `gradle.properties` with `.github/template-cleanup/gradle.properties`
|
||||
- name: Verify gradle.properties
|
||||
run: |
|
||||
echo "\`\`\`diff" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
diff -U 0 \
|
||||
-I '^pluginVersion' \
|
||||
-I '^pluginGroup' \
|
||||
-I '^pluginName' \
|
||||
-I '^pluginRepositoryUrl' \
|
||||
--label .github/template-cleanup/gradle.properties \
|
||||
--label gradle.properties \
|
||||
.github/template-cleanup/gradle.properties gradle.properties \
|
||||
>> $GITHUB_STEP_SUMMARY
|
||||
|
||||
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 1.0 MiB |
After Width: | Height: | Size: 5.3 MiB |
@ -0,0 +1,14 @@
|
||||
module example
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
gorm.io/driver/mysql v1.5.1
|
||||
gorm.io/gorm v1.25.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
)
|
@ -0,0 +1,11 @@
|
||||
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw=
|
||||
gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o=
|
||||
gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
|
||||
gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"log"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID uint // 主键
|
||||
Name string // 姓名
|
||||
Email *string // 邮箱
|
||||
}
|
||||
|
||||
func (u *User) TableName() string {
|
||||
return "users"
|
||||
}
|
||||
|
||||
type User2 struct {
|
||||
ID uint // 主键2
|
||||
Name string // 姓名2
|
||||
Email *string // 邮箱2
|
||||
}
|
||||
|
||||
type Post struct {
|
||||
ID int32 `gorm:"column:id;type:int(12);primaryKey" json:"id"` // 主讲
|
||||
Context int32 `gorm:"column:body;type:tinyint(4);not null" json:"body"` // 内容
|
||||
CreateTime int32 `gorm:"column:created_at;not null" json:"created_at"` // 创建时间
|
||||
}
|
||||
|
||||
func main() {
|
||||
dsn := ""
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// @Model(User)
|
||||
query1 := db.Select("id", "name")
|
||||
query1 = query1.Where("name = ?", "")
|
||||
|
||||
var user2 User2
|
||||
query2 := db.Where("name <> ?", "")
|
||||
query2.Where("id > ?").Find(&user2)
|
||||
|
||||
var post Post
|
||||
query3 := db.Select("body", "created_at")
|
||||
query3 = query3.Where("id IN ?", "")
|
||||
query3.Find(&post)
|
||||
}
|
@ -1 +1 @@
|
||||
rootProject.name = "IntelliJ Platform Plugin Template"
|
||||
rootProject.name = "Go ORM Helper"
|
@ -0,0 +1,69 @@
|
||||
package com.github.maiqingqiang.goormhelper;
|
||||
|
||||
import com.alibaba.druid.DbType;
|
||||
import com.github.maiqingqiang.goormhelper.sql2struct.ISQL2Struct;
|
||||
import com.github.maiqingqiang.goormhelper.sql2struct.impl.SQL2GormStruct;
|
||||
import com.github.maiqingqiang.goormhelper.sql2struct.impl.SQL2Struct;
|
||||
import com.github.maiqingqiang.goormhelper.sql2struct.impl.SQL2XormStruct;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public interface Types {
|
||||
String MODEL_ANNOTATION = "@Model";
|
||||
Pattern MODEL_ANNOTATION_PATTERN = Pattern.compile(MODEL_ANNOTATION + "\\((.*?)\\)");
|
||||
String TABLE_ANNOTATION = "@Table";
|
||||
Pattern TABLE_ANNOTATION_PATTERN = Pattern.compile(TABLE_ANNOTATION + "\\((.*?)\\)");
|
||||
|
||||
enum ORM {
|
||||
AskEveryTime(GoORMHelperBundle.message("orm.AskEveryTime")),
|
||||
General(GoORMHelperBundle.message("orm.General")),
|
||||
Gorm("Gorm"),
|
||||
Xorm("Xorm");
|
||||
|
||||
private final String name;
|
||||
|
||||
ORM(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ISQL2Struct sql2Struct(String sql, DbType dbType) {
|
||||
return switch (this) {
|
||||
case General -> new SQL2Struct(sql, dbType);
|
||||
case Gorm -> new SQL2GormStruct(sql, dbType);
|
||||
case Xorm -> new SQL2XormStruct(sql, dbType);
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
enum Database {
|
||||
AskEveryTime(GoORMHelperBundle.message("database.AskEveryTime")),
|
||||
MySQL("MySQL"),
|
||||
PostgreSQL("PostgreSQL");
|
||||
|
||||
private final String name;
|
||||
|
||||
Database(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public DbType toDbType() {
|
||||
return switch (this) {
|
||||
case MySQL -> DbType.mysql;
|
||||
case PostgreSQL -> DbType.postgresql;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package com.github.maiqingqiang.goormhelper.actions;
|
||||
|
||||
import com.github.maiqingqiang.goormhelper.Types;
|
||||
import com.github.maiqingqiang.goormhelper.services.GoORMHelperProjectSettings;
|
||||
import com.github.maiqingqiang.goormhelper.sql2struct.ISQL2Struct;
|
||||
import com.github.maiqingqiang.goormhelper.ui.ConvertSettingDialogWrapper;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Caret;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
|
||||
import com.intellij.openapi.ide.CopyPasteManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import net.sf.jsqlparser.util.validation.Validation;
|
||||
import net.sf.jsqlparser.util.validation.ValidationError;
|
||||
import net.sf.jsqlparser.util.validation.feature.FeaturesAllowed;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class EditorPasteListener extends EditorActionHandler {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(EditorPasteListener.class);
|
||||
|
||||
private final EditorActionHandler handler;
|
||||
|
||||
public EditorPasteListener(EditorActionHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doExecute(@NotNull Editor editor, @Nullable Caret caret, DataContext dataContext) {
|
||||
String text = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
|
||||
|
||||
if (verifySQL(text)) {
|
||||
Project project = editor.getProject();
|
||||
|
||||
GoORMHelperProjectSettings.State state = Objects.requireNonNull(GoORMHelperProjectSettings.getInstance(Objects.requireNonNull(project)).getState());
|
||||
|
||||
Types.ORM selectedORM = state.defaultORM;
|
||||
Types.Database selectedDatabase = state.defaultDatabase;
|
||||
|
||||
if (selectedORM == Types.ORM.AskEveryTime || selectedDatabase == Types.Database.AskEveryTime) {
|
||||
ConvertSettingDialogWrapper wrapper = new ConvertSettingDialogWrapper(project);
|
||||
if (!wrapper.showAndGet()) {
|
||||
this.handler.execute(editor, caret, dataContext);
|
||||
return;
|
||||
}
|
||||
|
||||
selectedORM = (Types.ORM) wrapper.getOrmComponent().getComponent().getSelectedItem();
|
||||
selectedDatabase = (Types.Database) wrapper.getDatabaseComponent().getComponent().getSelectedItem();
|
||||
}
|
||||
|
||||
final Types.ORM finalSelectedORM = selectedORM;
|
||||
final Types.Database finalSelectedDatabase = selectedDatabase;
|
||||
|
||||
WriteCommandAction.runWriteCommandAction(editor.getProject(), () -> {
|
||||
if (text == null || text.isEmpty() || finalSelectedORM == null || finalSelectedDatabase == null) return;
|
||||
|
||||
ISQL2Struct sql2Struct = finalSelectedORM.sql2Struct(text, finalSelectedDatabase.toDbType());
|
||||
|
||||
Caret currentCaret = editor.getCaretModel().getCurrentCaret();
|
||||
int start = currentCaret.getSelectionStart();
|
||||
|
||||
editor.getDocument().insertString(start, sql2Struct.convert());
|
||||
});
|
||||
} else {
|
||||
this.handler.execute(editor, caret, dataContext);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean verifySQL(String sql) {
|
||||
|
||||
Validation validation = new Validation(Collections.singletonList(FeaturesAllowed.CREATE), sql);
|
||||
List<ValidationError> errors = validation.validate();
|
||||
|
||||
for (ValidationError error : errors) {
|
||||
LOG.warn(error.toString());
|
||||
}
|
||||
|
||||
return errors.size() == 0;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.github.maiqingqiang.goormhelper.actions;
|
||||
|
||||
import com.github.maiqingqiang.goormhelper.Types;
|
||||
import com.github.maiqingqiang.goormhelper.services.GoORMHelperProjectSettings;
|
||||
import com.github.maiqingqiang.goormhelper.sql2struct.ISQL2Struct;
|
||||
import com.github.maiqingqiang.goormhelper.sql2struct.impl.SQL2GormStruct;
|
||||
import com.github.maiqingqiang.goormhelper.ui.ConvertSettingDialogWrapper;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.Caret;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class SQL2StructAction extends AnAction {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
|
||||
GoORMHelperProjectSettings.State state = Objects.requireNonNull(GoORMHelperProjectSettings.getInstance(Objects.requireNonNull(e.getProject())).getState());
|
||||
|
||||
Types.ORM selectedORM = state.defaultORM;
|
||||
Types.Database selectedDatabase = state.defaultDatabase;
|
||||
|
||||
if (selectedORM == Types.ORM.AskEveryTime || selectedDatabase == Types.Database.AskEveryTime) {
|
||||
ConvertSettingDialogWrapper wrapper = new ConvertSettingDialogWrapper(e.getProject());
|
||||
if (!wrapper.showAndGet()) return;
|
||||
|
||||
selectedORM = (Types.ORM) wrapper.getOrmComponent().getComponent().getSelectedItem();
|
||||
selectedDatabase = (Types.Database) wrapper.getDatabaseComponent().getComponent().getSelectedItem();
|
||||
}
|
||||
|
||||
Editor editor = e.getData(CommonDataKeys.EDITOR);
|
||||
if (editor == null) return;
|
||||
|
||||
String text = editor.getSelectionModel().getSelectedText();
|
||||
|
||||
Caret currentCaret = editor.getCaretModel().getCurrentCaret();
|
||||
int start = currentCaret.getSelectionStart();
|
||||
int end = currentCaret.getSelectionEnd();
|
||||
|
||||
final Types.ORM finalSelectedORM = selectedORM;
|
||||
final Types.Database finalSelectedDatabase = selectedDatabase;
|
||||
|
||||
WriteCommandAction.runWriteCommandAction(e.getProject(), () -> {
|
||||
if (text == null || text.isEmpty() || finalSelectedORM == null || finalSelectedDatabase == null) return;
|
||||
|
||||
ISQL2Struct sql2Struct = finalSelectedORM.sql2Struct(text, finalSelectedDatabase.toDbType());
|
||||
|
||||
editor.getDocument().replaceString(start, end, sql2Struct.convert());
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.github.maiqingqiang.goormhelper.bean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@lombok.NoArgsConstructor
|
||||
@lombok.Data
|
||||
public class ScannedPath {
|
||||
private List<String> schema = new ArrayList<>();
|
||||
private long lastModified;
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package com.github.maiqingqiang.goormhelper.codeInsights;
|
||||
|
||||
import com.github.maiqingqiang.goormhelper.Types;
|
||||
import com.goide.psi.GoFile;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightVisitor;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class GoORMHelperHighlightVisitor implements HighlightVisitor {
|
||||
private HighlightInfoHolder holder;
|
||||
|
||||
@Override
|
||||
public boolean suitableForFile(@NotNull PsiFile file) {
|
||||
return file instanceof GoFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull PsiElement element) {
|
||||
if (element instanceof PsiComment psiComment) {
|
||||
modelAnnotation(psiComment);
|
||||
tableAnnotation(psiComment);
|
||||
}
|
||||
}
|
||||
|
||||
private void modelAnnotation(PsiComment psiComment) {
|
||||
int index = psiComment.getText().indexOf(Types.MODEL_ANNOTATION);
|
||||
|
||||
if (index > -1) {
|
||||
Matcher matcher;
|
||||
if ((matcher = Types.MODEL_ANNOTATION_PATTERN.matcher(psiComment.getText())).find()) {
|
||||
holder.add(HighlightInfo.newHighlightInfo(
|
||||
new HighlightInfoType.HighlightInfoTypeImpl(
|
||||
HighlightSeverity.INFORMATION,
|
||||
DefaultLanguageHighlighterColors.METADATA)
|
||||
).range(psiComment, TextRange.from(index, Types.MODEL_ANNOTATION.length())).create());
|
||||
|
||||
holder.add(HighlightInfo.newHighlightInfo(
|
||||
new HighlightInfoType.HighlightInfoTypeImpl(
|
||||
HighlightSeverity.INFORMATION, DefaultLanguageHighlighterColors.IDENTIFIER)
|
||||
).range(psiComment, TextRange.from(index + Types.MODEL_ANNOTATION.length(), matcher.group(0).length() - Types.MODEL_ANNOTATION.length())).create());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void tableAnnotation(PsiComment psiComment) {
|
||||
int index = psiComment.getText().indexOf(Types.TABLE_ANNOTATION);
|
||||
|
||||
if (index > -1) {
|
||||
Matcher matcher;
|
||||
if ((matcher = Types.TABLE_ANNOTATION_PATTERN.matcher(psiComment.getText())).find()) {
|
||||
holder.add(HighlightInfo.newHighlightInfo(
|
||||
new HighlightInfoType.HighlightInfoTypeImpl(
|
||||
HighlightSeverity.INFORMATION,
|
||||
DefaultLanguageHighlighterColors.METADATA)
|
||||
).range(psiComment, TextRange.from(index, Types.TABLE_ANNOTATION.length())).create());
|
||||
|
||||
holder.add(HighlightInfo.newHighlightInfo(
|
||||
new HighlightInfoType.HighlightInfoTypeImpl(
|
||||
HighlightSeverity.INFORMATION, DefaultLanguageHighlighterColors.IDENTIFIER)
|
||||
).range(psiComment, TextRange.from(index + Types.TABLE_ANNOTATION.length(), matcher.group(0).length() - Types.TABLE_ANNOTATION.length())).create());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean analyze(@NotNull PsiFile file, boolean updateWholeFile, @NotNull HighlightInfoHolder holder, @NotNull Runnable action) {
|
||||
this.holder = holder;
|
||||
try {
|
||||
action.run();
|
||||
} finally {
|
||||
this.holder = null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HighlightVisitor clone() {
|
||||
return new GoORMHelperHighlightVisitor();
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package com.github.maiqingqiang.goormhelper.listeners;
|
||||
|
||||
import com.github.maiqingqiang.goormhelper.GoORMHelperBundle;
|
||||
import com.github.maiqingqiang.goormhelper.actions.EditorPasteListener;
|
||||
import com.github.maiqingqiang.goormhelper.services.GoORMHelperManager;
|
||||
import com.github.maiqingqiang.goormhelper.services.GoORMHelperProjectSettings;
|
||||
import com.goide.GoFileType;
|
||||
import com.goide.psi.GoFile;
|
||||
import com.goide.psi.GoStructType;
|
||||
import com.goide.psi.GoTypeSpec;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.progress.BackgroundTaskQueue;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManagerListener;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.workspaceModel.ide.VirtualFileUrlManagerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MyProjectManagerListener implements ProjectManagerListener {
|
||||
private static final Logger LOG = Logger.getInstance(MyProjectManagerListener.class);
|
||||
|
||||
@Override
|
||||
public void projectOpened(@NotNull Project project) {
|
||||
intializing(project);
|
||||
}
|
||||
|
||||
private void intializing(@NotNull Project project) {
|
||||
|
||||
BackgroundTaskQueue taskQueue = new BackgroundTaskQueue(project, GoORMHelperBundle.message("name"));
|
||||
taskQueue.run(new Task.Backgroundable(project, GoORMHelperBundle.message("initializing.title")) {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
GoORMHelperManager.getInstance(project).scan();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.github.maiqingqiang.goormhelper.listeners;
|
||||
|
||||
import com.github.maiqingqiang.goormhelper.bean.ScannedPath;
|
||||
import com.github.maiqingqiang.goormhelper.services.GoORMHelperManager;
|
||||
import com.goide.GoFileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SchemaFileListener implements BulkFileListener {
|
||||
|
||||
|
||||
private final Project project;
|
||||
|
||||
public SchemaFileListener(Project project) {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void after(@NotNull List<? extends @NotNull VFileEvent> events) {
|
||||
for (VFileEvent event : events) {
|
||||
if (event.isFromSave() && event.getFile() != null && event.getFile().isValid() && event.getPath().endsWith('.' + GoFileType.DEFAULT_EXTENSION)) {
|
||||
|
||||
VirtualFile file = event.getFile();
|
||||
|
||||
GoORMHelperManager goORMHelperManager = GoORMHelperManager.getInstance(this.project);
|
||||
|
||||
ScannedPath scannedPath = goORMHelperManager.getScannedPath(file);
|
||||
if (scannedPath == null) continue;
|
||||
goORMHelperManager.clearScanned(file);
|
||||
|
||||
goORMHelperManager.parseGoFile(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package com.github.maiqingqiang.goormhelper.orm.gorm;
|
||||
|
||||
import com.goide.inspections.core.GoCallableDescriptor;
|
||||
import com.goide.inspections.core.GoCallableDescriptorSet;
|
||||
import com.goide.inspections.core.GoMethodDescriptor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface GormTypes {
|
||||
Map<GoCallableDescriptor, Integer> GORM_CALLABLES = Map.ofEntries(
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Where"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Select"), -1),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Distinct"), -1),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).First"), 1),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Find"), 1),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Not"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Or"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Order"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Group"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Having"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Attrs"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Pluck"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Omit"), -1),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).UpdateColumn"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Delete"), 1),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Where"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Select"), -1),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Distinct"), -1),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).First"), 1),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Find"), 1),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Not"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Or"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Order"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Group"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Having"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Attrs"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Pluck"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Omit"), -1),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).UpdateColumn"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Delete"), 1)
|
||||
);
|
||||
|
||||
Map<GoCallableDescriptor, Integer> GORM_MODEL_CALLABLES = Map.ofEntries(
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Model"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).First"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Find"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Delete"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).FirstOrInit"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).FirstOrCreate"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Take"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Last"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Create"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Model"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).First"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Find"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Delete"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).FirstOrInit"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).FirstOrCreate"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Take"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Last"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Create"), 0)
|
||||
);
|
||||
|
||||
List<String> OPERATOR_EXPR = List.of(
|
||||
"%s = ?", "%s <> ?", "%s IN ?", "%s LIKE ?", "%s > ?", "%s BETWEEN ? AND ?");
|
||||
|
||||
Map<GoCallableDescriptor, List<String>> GORM_WHERE_EXPR = Map.ofEntries(
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Where"), OPERATOR_EXPR),
|
||||
Map.entry(GoMethodDescriptor.of("(*gorm.io/gorm.DB).Having"), OPERATOR_EXPR),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Where"), OPERATOR_EXPR),
|
||||
Map.entry(GoMethodDescriptor.of("(*github.com/jinzhu/gorm.DB).Having"), OPERATOR_EXPR)
|
||||
);
|
||||
|
||||
GoCallableDescriptorSet ORM_MODEL_CALLABLES_SET = new GoCallableDescriptorSet(GORM_MODEL_CALLABLES.keySet());
|
||||
|
||||
GoCallableDescriptorSet GORM_CALLABLES_SET = new GoCallableDescriptorSet(GORM_CALLABLES.keySet());
|
||||
}
|
@ -0,0 +1,298 @@
|
||||
package com.github.maiqingqiang.goormhelper.orm.gorm.codeInsights.completion;
|
||||
|
||||
import com.github.maiqingqiang.goormhelper.Types;
|
||||
import com.github.maiqingqiang.goormhelper.orm.gorm.GormTypes;
|
||||
import com.github.maiqingqiang.goormhelper.services.GoORMHelperManager;
|
||||
import com.github.maiqingqiang.goormhelper.ui.Icons;
|
||||
import com.github.maiqingqiang.goormhelper.utils.Strings;
|
||||
import com.goide.documentation.GoDocumentationProvider;
|
||||
import com.goide.inspections.core.GoCallableDescriptor;
|
||||
import com.goide.psi.*;
|
||||
import com.goide.psi.impl.GoPsiUtil;
|
||||
import com.google.common.base.CaseFormat;
|
||||
import com.intellij.codeInsight.completion.CompletionParameters;
|
||||
import com.intellij.codeInsight.completion.CompletionProvider;
|
||||
import com.intellij.codeInsight.completion.CompletionResultSet;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.ResolveState;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
public class GormColumnCompletionProvider extends CompletionProvider<CompletionParameters> {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(GormColumnCompletionProvider.class);
|
||||
|
||||
static boolean hasArgumentAtIndex(@NotNull GoCallExpr call, int argumentIndex, @NotNull PsiElement argument) {
|
||||
if (argumentIndex == -1) return true;
|
||||
argument = GoPsiUtil.skipParens(argument);
|
||||
return argument == ContainerUtil.getOrElse(call.getArgumentList().getExpressionList(), argumentIndex, (Object) null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
|
||||
Project project = parameters.getPosition().getProject();
|
||||
|
||||
GoCallExpr goCallExpr = (GoCallExpr) PsiTreeUtil.findFirstParent(parameters.getPosition(), element -> element instanceof GoCallExpr);
|
||||
|
||||
if (goCallExpr == null) return;
|
||||
|
||||
GoCallableDescriptor descriptor = GormTypes.GORM_CALLABLES_SET.find(goCallExpr, false);
|
||||
if (descriptor == null) return;
|
||||
|
||||
Integer argumentIndex = GormTypes.GORM_CALLABLES.get(descriptor);
|
||||
|
||||
if (!hasArgumentAtIndex(goCallExpr, argumentIndex, parameters.getPosition().getParent()) && !(parameters.getPosition().getParent().getParent() instanceof GoKey))
|
||||
return;
|
||||
|
||||
String schema = scanSchema(parameters.getPosition());
|
||||
|
||||
if (schema.isEmpty()) return;
|
||||
|
||||
List<String> pathList = Objects.requireNonNull(GoORMHelperManager.getInstance(project).getState()).schemaMapping.get(schema);
|
||||
|
||||
if (pathList == null) return;
|
||||
|
||||
for (String path : pathList) {
|
||||
|
||||
VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(path);
|
||||
if (file == null) continue;
|
||||
|
||||
GoFile goFile = (GoFile) PsiManager.getInstance(project).findFile(file);
|
||||
if (goFile == null) continue;
|
||||
|
||||
for (GoTypeDeclaration goTypeDeclaration : goFile.findChildrenByClass(GoTypeDeclaration.class)) {
|
||||
GoTypeSpec goTypeSpec = goTypeDeclaration.getTypeSpecList().get(0);
|
||||
|
||||
if (!Objects.equals(goTypeSpec.getName(), schema)) continue;
|
||||
|
||||
scanFields(descriptor, result, goTypeSpec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void scanFields(GoCallableDescriptor descriptor, @NotNull CompletionResultSet result, @NotNull GoTypeSpec goTypeSpec) {
|
||||
if (goTypeSpec.getSpecType().getType() instanceof GoStructType goStructType) {
|
||||
for (GoFieldDeclaration field : goStructType.getFieldDeclarationList()) {
|
||||
String column = "";
|
||||
String comment = "";
|
||||
String type = "";
|
||||
|
||||
if (field.getType() != null) {
|
||||
type = field.getType().getPresentationText();
|
||||
}
|
||||
|
||||
GoTag tag = field.getTag();
|
||||
if (tag != null && tag.getValue("gorm") != null) {
|
||||
Map<String, String> tagMap = parseTag(Objects.requireNonNull(tag.getValue("gorm")));
|
||||
|
||||
if (tagMap.containsKey("COLUMN")) {
|
||||
column = tagMap.get("COLUMN");
|
||||
}
|
||||
|
||||
if (tagMap.containsKey("COMMENT")) {
|
||||
comment = tagMap.get("COMMENT");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (column.isEmpty()) {
|
||||
|
||||
if (field.getFieldDefinitionList().size() == 0 && field.getAnonymousFieldDefinition() != null) {
|
||||
GoType goType = field.getAnonymousFieldDefinition().getGoType(ResolveState.initial());
|
||||
if (goType == null) continue;
|
||||
|
||||
GoTypeSpec spec = (GoTypeSpec) goType.resolve(ResolveState.initial());
|
||||
if (spec == null) continue;
|
||||
|
||||
scanFields(descriptor, result, spec);
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = field.getFieldDefinitionList().get(0).getName();
|
||||
|
||||
if (name != null) {
|
||||
column = Strings.replaceCommonInitialisms(name);
|
||||
column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, column);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (comment.isEmpty()) {
|
||||
comment = GoDocumentationProvider.getCommentText(GoDocumentationProvider.getCommentsForElement(field), false);
|
||||
}
|
||||
|
||||
addElement(result, column, comment, type);
|
||||
|
||||
List<String> whereExpr = GormTypes.GORM_WHERE_EXPR.get(descriptor);
|
||||
if (whereExpr != null) {
|
||||
for (String s : whereExpr) {
|
||||
addElement(result, String.format(s, column), comment, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String scanSchema(@NotNull PsiElement psiElement) {
|
||||
|
||||
String schema = "";
|
||||
|
||||
GoStatement currentStatement = (GoStatement) PsiTreeUtil.findFirstParent(psiElement, element -> element instanceof GoStatement);
|
||||
|
||||
if (currentStatement == null) return schema;
|
||||
|
||||
schema = findSchema(currentStatement);
|
||||
if (!schema.isEmpty()) return schema;
|
||||
|
||||
|
||||
GoVarDefinition currentGoVarDefinition = PsiTreeUtil.findChildOfType(currentStatement, GoVarDefinition.class);
|
||||
if (currentGoVarDefinition != null) {
|
||||
schema = searchGoVarDefinitionReferences(currentGoVarDefinition);
|
||||
if (!schema.isEmpty()) return schema;
|
||||
}
|
||||
|
||||
GoReferenceExpression lastGoReferenceExpression = null;
|
||||
|
||||
for (GoReferenceExpression goReferenceExpression : PsiTreeUtil.findChildrenOfType(currentStatement, GoReferenceExpression.class)) {
|
||||
GoType goType = goReferenceExpression.getGoType(ResolveState.initial());
|
||||
if (goType != null && goType.getPresentationText().equals("*DB")) {
|
||||
lastGoReferenceExpression = goReferenceExpression;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastGoReferenceExpression != null) {
|
||||
GoVarDefinition goVarDefinition = (GoVarDefinition) lastGoReferenceExpression.resolve();
|
||||
|
||||
GoStatement resolveStatement = (GoStatement) PsiTreeUtil.findFirstParent(goVarDefinition, element -> element instanceof GoStatement);
|
||||
if (resolveStatement == null) return schema;
|
||||
schema = findSchema(resolveStatement);
|
||||
if (!schema.isEmpty()) return schema;
|
||||
|
||||
schema = searchGoVarDefinitionReferences(goVarDefinition);
|
||||
if (!schema.isEmpty()) return schema;
|
||||
|
||||
scanSchema(goVarDefinition);
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
|
||||
private String searchGoVarDefinitionReferences(GoVarDefinition goVarDefinition) {
|
||||
String schema = "";
|
||||
for (PsiReference psiReference : GoReferencesSearch.search(goVarDefinition)) {
|
||||
GoStatement statement = (GoStatement) PsiTreeUtil.findFirstParent(psiReference.getElement(), element -> element instanceof GoStatement);
|
||||
if (statement == null) continue;
|
||||
System.out.println("statement " + statement.getText());
|
||||
schema = findSchema(statement);
|
||||
if (!schema.isEmpty()) return schema;
|
||||
|
||||
for (GoVarDefinition varDefinition : PsiTreeUtil.findChildrenOfType(statement, GoVarDefinition.class)) {
|
||||
GoType goType = varDefinition.getGoType(ResolveState.initial());
|
||||
|
||||
if (goType != null && goType.getPresentationText().equals("*DB")) {
|
||||
return searchGoVarDefinitionReferences(varDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
|
||||
private static void addElement(@NotNull CompletionResultSet result, String column, String comment, String type) {
|
||||
result.addElement(LookupElementBuilder.create(column)
|
||||
.withTypeText(type)
|
||||
.withIcon(Icons.Gorm35x12)
|
||||
.withTailText(" " + comment, true));
|
||||
}
|
||||
|
||||
private static String findSchema(@NotNull GoStatement statement) {
|
||||
String schema = "";
|
||||
|
||||
String comment = GoDocumentationProvider.getCommentText(GoDocumentationProvider.getCommentsForElement(statement), false);
|
||||
Matcher matcher;
|
||||
if ((matcher = Types.MODEL_ANNOTATION_PATTERN.matcher(comment)).find()) schema = matcher.group(1);
|
||||
|
||||
if (!schema.isEmpty()) return schema;
|
||||
|
||||
for (GoCallExpr goCallExpr : PsiTreeUtil.findChildrenOfType(statement, GoCallExpr.class)) {
|
||||
GoCallableDescriptor descriptor = GormTypes.ORM_MODEL_CALLABLES_SET.find(goCallExpr, false);
|
||||
if (descriptor == null) continue;
|
||||
|
||||
Integer argumentIndex = GormTypes.GORM_MODEL_CALLABLES.get(descriptor);
|
||||
|
||||
System.out.println("argumentIndex " + argumentIndex);
|
||||
System.out.println("getExpressionList " + goCallExpr.getArgumentList().getExpressionList().get(argumentIndex));
|
||||
|
||||
GoExpression argument = goCallExpr.getArgumentList().getExpressionList().get(argumentIndex);
|
||||
|
||||
if (argument instanceof GoUnaryExpr goUnaryExpr) {
|
||||
if (goUnaryExpr.getExpression() instanceof GoCompositeLit goCompositeLit) {
|
||||
if (goCompositeLit.getTypeReferenceExpression() == null) continue;
|
||||
schema = goCompositeLit.getTypeReferenceExpression().getIdentifier().getText();
|
||||
} else if (goUnaryExpr.getExpression() instanceof GoReferenceExpression goReferenceExpression) {
|
||||
GoVarDefinition goVarDefinition = (GoVarDefinition) goReferenceExpression.resolve();
|
||||
|
||||
if (goVarDefinition == null) continue;
|
||||
|
||||
GoType goType = goVarDefinition.getGoType(ResolveState.initial());
|
||||
if (goType == null || goType.getTypeReferenceExpression() == null) continue;
|
||||
|
||||
schema = goType.getTypeReferenceExpression().getIdentifier().getText();
|
||||
}
|
||||
} else if (argument instanceof GoBuiltinCallExpr goBuiltinCallExpr) {
|
||||
GoType goType = PsiTreeUtil.findChildOfType(goBuiltinCallExpr, GoType.class);
|
||||
if (goType == null || goType.getTypeReferenceExpression() == null) continue;
|
||||
schema = goType.getTypeReferenceExpression().getIdentifier().getText();
|
||||
} else if (argument instanceof GoReferenceExpression goReferenceExpression && goReferenceExpression.resolve() instanceof GoVarDefinition goVarDefinition) {
|
||||
GoType goType = PsiTreeUtil.findChildOfType(goVarDefinition.getParent(), GoType.class);
|
||||
if (goType != null) {
|
||||
if (goType.getTypeReferenceExpression() == null) continue;
|
||||
schema = goType.getTypeReferenceExpression().getIdentifier().getText();
|
||||
} else {
|
||||
GoCompositeLit goCompositeLit = PsiTreeUtil.findChildOfType(goVarDefinition.getParent(), GoCompositeLit.class);
|
||||
if (goCompositeLit == null || goCompositeLit.getTypeReferenceExpression() == null) continue;
|
||||
schema = goCompositeLit.getTypeReferenceExpression().getIdentifier().getText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
||||
public static @NotNull Map<String, String> parseTag(@NotNull String str) {
|
||||
Map<String, String> settings = new HashMap<>();
|
||||
String[] names = str.split(";");
|
||||
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
int j = i;
|
||||
if (names[j].length() > 0) {
|
||||
while (names[j].charAt(names[j].length() - 1) == '\\') {
|
||||
i++;
|
||||
names[j] = names[j].substring(0, names[j].length() - 1) + ";" + names[i];
|
||||
names[i] = "";
|
||||
}
|
||||
}
|
||||
|
||||
String[] values = names[j].split(":");
|
||||
String k = values[0].trim().toUpperCase();
|
||||
|
||||
if (values.length >= 2) {
|
||||
settings.put(k, String.join(":", Arrays.copyOfRange(values, 1, values.length)));
|
||||
} else if (!k.equals("")) {
|
||||
settings.put(k, k);
|
||||
}
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.github.maiqingqiang.goormhelper.orm.gorm.codeInsights.completion;
|
||||
|
||||
import com.github.maiqingqiang.goormhelper.orm.gorm.GormTypes;
|
||||
import com.goide.GoParserDefinition;
|
||||
import com.goide.psi.GoCallExpr;
|
||||
import com.intellij.codeInsight.completion.CompletionContributor;
|
||||
import com.intellij.codeInsight.completion.CompletionType;
|
||||
import com.intellij.patterns.PlatformPatterns;
|
||||
import com.intellij.patterns.PsiElementPattern;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class GormCompletionContributor extends CompletionContributor {
|
||||
public GormCompletionContributor() {
|
||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement()
|
||||
.withElementType(GoParserDefinition.Lazy.STRING_LITERALS)
|
||||
.withSuperParent(3, new PsiElementPattern.Capture<>(GoCallExpr.class) {
|
||||
@Override
|
||||
public boolean accepts(@Nullable Object o, ProcessingContext context) {
|
||||
return o instanceof GoCallExpr && GormTypes.GORM_CALLABLES_SET.find((GoCallExpr) o, false) != null;
|
||||
}
|
||||
}).andOr(PlatformPatterns.psiElement()),
|
||||
new GormColumnCompletionProvider());
|
||||
|
||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement()
|
||||
.withElementType(GoParserDefinition.Lazy.STRING_LITERALS)
|
||||
.withSuperParent(7, new PsiElementPattern.Capture<>(GoCallExpr.class) {
|
||||
@Override
|
||||
public boolean accepts(@Nullable Object o, ProcessingContext context) {
|
||||
return o instanceof GoCallExpr && GormTypes.GORM_CALLABLES_SET.find((GoCallExpr) o, false) != null;
|
||||
}
|
||||
}),
|
||||
new GormColumnCompletionProvider());
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.github.maiqingqiang.goormhelper.orm.gorm.codeInsights.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionParameters;
|
||||
import com.intellij.codeInsight.completion.CompletionProvider;
|
||||
import com.intellij.codeInsight.completion.CompletionResultSet;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class GormTagCompletionProvider extends CompletionProvider<CompletionParameters> {
|
||||
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.github.maiqingqiang.goormhelper.orm.xorm;
|
||||
|
||||
import com.goide.inspections.core.GoCallableDescriptor;
|
||||
import com.goide.inspections.core.GoCallableDescriptorSet;
|
||||
import com.goide.inspections.core.GoMethodDescriptor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface XormTypes {
|
||||
Map<GoCallableDescriptor, Integer> XORM_CALLABLES = Map.ofEntries(
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Engine).Where"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Where"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).And"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Asc"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Desc"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Engine).Select"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Select"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Engine).In"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).In"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Or"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Engine).Cols"), -1),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Cols"), -1),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Engine).Omit"), -1),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Omit"), -1),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Engine).Distinct"), -1),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Distinct"), -1),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Engine).GroupBy"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).GroupBy"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Engine).Having"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Having"), 0)
|
||||
);
|
||||
|
||||
Map<GoCallableDescriptor, Integer> XORM_MODEL_CALLABLES = Map.ofEntries(
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Get"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Find"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Count"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Iterate"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Rows"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Sum"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Update"), 0),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Delete"), 0)
|
||||
);
|
||||
|
||||
List<String> OPERATOR_EXPR = List.of(
|
||||
"%s = ?", "%s <> ?", "%s IN ?", "%s LIKE ?", "%s > ?", "%s BETWEEN ? AND ?");
|
||||
|
||||
Map<GoCallableDescriptor, List<String>> XORM_WHERE_EXPR = Map.ofEntries(
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Engine).Where"), OPERATOR_EXPR),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Where"), OPERATOR_EXPR),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).And"), OPERATOR_EXPR),
|
||||
Map.entry(GoMethodDescriptor.of("(*xorm.io/xorm.Session).Or"), OPERATOR_EXPR)
|
||||
);
|
||||
|
||||
GoCallableDescriptorSet XORM_MODEL_CALLABLES_SET = new GoCallableDescriptorSet(XORM_MODEL_CALLABLES.keySet());
|
||||
|
||||
GoCallableDescriptorSet XORM_CALLABLES_SET = new GoCallableDescriptorSet(XORM_CALLABLES.keySet());
|
||||
}
|
@ -0,0 +1,337 @@
|
||||
package com.github.maiqingqiang.goormhelper.orm.xorm.completion;
|
||||
|
||||
import com.github.maiqingqiang.goormhelper.Types;
|
||||
import com.github.maiqingqiang.goormhelper.orm.xorm.XormTypes;
|
||||
import com.github.maiqingqiang.goormhelper.services.GoORMHelperManager;
|
||||
import com.github.maiqingqiang.goormhelper.ui.Icons;
|
||||
import com.github.maiqingqiang.goormhelper.utils.Strings;
|
||||
import com.goide.documentation.GoDocumentationProvider;
|
||||
import com.goide.inspections.core.GoCallableDescriptor;
|
||||
import com.goide.psi.*;
|
||||
import com.goide.psi.impl.GoPsiUtil;
|
||||
import com.google.common.base.CaseFormat;
|
||||
import com.intellij.codeInsight.completion.CompletionParameters;
|
||||
import com.intellij.codeInsight.completion.CompletionProvider;
|
||||
import com.intellij.codeInsight.completion.CompletionResultSet;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.ResolveState;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
public class XormColumnCompletionProvider extends CompletionProvider<CompletionParameters> {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(XormColumnCompletionProvider.class);
|
||||
|
||||
@lombok.Data
|
||||
static class Tag {
|
||||
private String name;
|
||||
private List<String> params;
|
||||
|
||||
public Tag(String name, List<String> params) {
|
||||
this.name = name;
|
||||
this.params = params;
|
||||
}
|
||||
}
|
||||
|
||||
static boolean hasArgumentAtIndex(@NotNull GoCallExpr call, int argumentIndex, @NotNull PsiElement argument) {
|
||||
if (argumentIndex == -1) return true;
|
||||
argument = GoPsiUtil.skipParens(argument);
|
||||
return argument == ContainerUtil.getOrElse(call.getArgumentList().getExpressionList(), argumentIndex, (Object) null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
|
||||
Project project = parameters.getPosition().getProject();
|
||||
|
||||
GoCallExpr goCallExpr = (GoCallExpr) PsiTreeUtil.findFirstParent(parameters.getPosition(), element -> element instanceof GoCallExpr);
|
||||
|
||||
if (goCallExpr == null) return;
|
||||
|
||||
GoCallableDescriptor descriptor = XormTypes.XORM_CALLABLES_SET.find(goCallExpr, false);
|
||||
|
||||
if (descriptor == null) return;
|
||||
|
||||
Integer argumentIndex = XormTypes.XORM_CALLABLES.get(descriptor);
|
||||
|
||||
if (!hasArgumentAtIndex(goCallExpr, argumentIndex, parameters.getPosition().getParent())) return;
|
||||
|
||||
String schema = scanSchema(parameters.getPosition());
|
||||
|
||||
if (schema.isEmpty()) return;
|
||||
|
||||
List<String> pathList = Objects.requireNonNull(GoORMHelperManager.getInstance(project).getState()).schemaMapping.get(schema);
|
||||
|
||||
if (pathList == null) return;
|
||||
|
||||
for (String path : pathList) {
|
||||
|
||||
VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(path);
|
||||
if (file == null) continue;
|
||||
|
||||
GoFile goFile = (GoFile) PsiManager.getInstance(project).findFile(file);
|
||||
if (goFile == null) continue;
|
||||
|
||||
for (GoTypeDeclaration goTypeDeclaration : goFile.findChildrenByClass(GoTypeDeclaration.class)) {
|
||||
GoTypeSpec goTypeSpec = goTypeDeclaration.getTypeSpecList().get(0);
|
||||
|
||||
if (!Objects.equals(goTypeSpec.getName(), schema)) continue;
|
||||
|
||||
scanFields(descriptor, result, goTypeSpec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void scanFields(GoCallableDescriptor descriptor, @NotNull CompletionResultSet result, @NotNull GoTypeSpec goTypeSpec) {
|
||||
if (goTypeSpec.getSpecType().getType() instanceof GoStructType goStructType) {
|
||||
for (GoFieldDeclaration field : goStructType.getFieldDeclarationList()) {
|
||||
String column = "";
|
||||
String comment = "";
|
||||
String type = "";
|
||||
|
||||
if (field.getType() != null) {
|
||||
type = field.getType().getPresentationText();
|
||||
}
|
||||
|
||||
GoTag tag = field.getTag();
|
||||
if (tag != null && tag.getValue("xorm") != null) {
|
||||
@NotNull List<Tag> tags = parseTag(tag.getValue("xorm"));
|
||||
|
||||
for (Tag t : tags) {
|
||||
if (t.getName().startsWith("'") && t.getParams().size() == 0) {
|
||||
column = t.getName().replaceAll("'", "");
|
||||
}
|
||||
|
||||
if (t.getName().equals("comment") && t.getParams().size() > 0) {
|
||||
comment = t.getParams().get(0).replaceAll("'", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (column.isEmpty()) {
|
||||
String name = field.getFieldDefinitionList().get(0).getName();
|
||||
|
||||
if (name != null) {
|
||||
column = Strings.replaceCommonInitialisms(name);
|
||||
column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, column);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (comment.isEmpty()) {
|
||||
comment = GoDocumentationProvider.getCommentText(GoDocumentationProvider.getCommentsForElement(field), false);
|
||||
}
|
||||
|
||||
addElement(result, column, comment, type);
|
||||
|
||||
List<String> whereExpr = XormTypes.XORM_WHERE_EXPR.get(descriptor);
|
||||
if (whereExpr != null) {
|
||||
for (String s : whereExpr) {
|
||||
addElement(result, String.format(s, column), comment, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String scanSchema(@NotNull PsiElement psiElement) {
|
||||
|
||||
String schema = "";
|
||||
|
||||
GoStatement currentStatement = (GoStatement) PsiTreeUtil.findFirstParent(psiElement, element -> element instanceof GoStatement);
|
||||
|
||||
if (currentStatement == null) return schema;
|
||||
|
||||
schema = findSchema(currentStatement);
|
||||
if (!schema.isEmpty()) return schema;
|
||||
|
||||
|
||||
GoVarDefinition currentGoVarDefinition = PsiTreeUtil.findChildOfType(currentStatement, GoVarDefinition.class);
|
||||
if (currentGoVarDefinition != null) {
|
||||
schema = searchGoVarDefinitionReferences(currentGoVarDefinition);
|
||||
if (!schema.isEmpty()) return schema;
|
||||
}
|
||||
|
||||
GoReferenceExpression lastGoReferenceExpression = null;
|
||||
|
||||
for (GoReferenceExpression goReferenceExpression : PsiTreeUtil.findChildrenOfType(currentStatement, GoReferenceExpression.class)) {
|
||||
GoType goType = goReferenceExpression.getGoType(ResolveState.initial());
|
||||
if (goType != null && (goType.getPresentationText().equals("*Session") || goType.getPresentationText().equals("*DB"))) {
|
||||
lastGoReferenceExpression = goReferenceExpression;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastGoReferenceExpression != null) {
|
||||
GoVarDefinition goVarDefinition = (GoVarDefinition) lastGoReferenceExpression.resolve();
|
||||
|
||||
GoStatement resolveStatement = (GoStatement) PsiTreeUtil.findFirstParent(goVarDefinition, element -> element instanceof GoStatement);
|
||||
if (resolveStatement == null) return schema;
|
||||
schema = findSchema(resolveStatement);
|
||||
if (!schema.isEmpty()) return schema;
|
||||
|
||||
schema = searchGoVarDefinitionReferences(goVarDefinition);
|
||||
if (!schema.isEmpty()) return schema;
|
||||
|
||||
scanSchema(goVarDefinition);
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
|
||||
private String searchGoVarDefinitionReferences(GoVarDefinition goVarDefinition) {
|
||||
String schema = "";
|
||||
for (PsiReference psiReference : GoReferencesSearch.search(goVarDefinition)) {
|
||||
GoStatement statement = (GoStatement) PsiTreeUtil.findFirstParent(psiReference.getElement(), element -> element instanceof GoStatement);
|
||||
if (statement == null) continue;
|
||||
schema = findSchema(statement);
|
||||
if (!schema.isEmpty()) return schema;
|
||||
|
||||
for (GoVarDefinition varDefinition : PsiTreeUtil.findChildrenOfType(statement, GoVarDefinition.class)) {
|
||||
GoType goType = varDefinition.getGoType(ResolveState.initial());
|
||||
|
||||
if (goType != null && (goType.getPresentationText().equals("*Session") || goType.getPresentationText().equals("*DB"))) {
|
||||
return searchGoVarDefinitionReferences(varDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
|
||||
private static void addElement(@NotNull CompletionResultSet result, String column, String comment, String type) {
|
||||
result.addElement(LookupElementBuilder.create(column)
|
||||
.withTypeText(type)
|
||||
.withIcon(Icons.Xorm19x12)
|
||||
.withTailText(" " + comment, true));
|
||||
}
|
||||
|
||||
private static String findSchema(@NotNull GoStatement statement) {
|
||||
String schema = "";
|
||||
|
||||
String comment = GoDocumentationProvider.getCommentText(GoDocumentationProvider.getCommentsForElement(statement), false);
|
||||
Matcher matcher;
|
||||
if ((matcher = Types.MODEL_ANNOTATION_PATTERN.matcher(comment)).find()) schema = matcher.group(1);
|
||||
|
||||
if (!schema.isEmpty()) return schema;
|
||||
|
||||
for (GoCallExpr goCallExpr : PsiTreeUtil.findChildrenOfType(statement, GoCallExpr.class)) {
|
||||
GoCallableDescriptor descriptor = XormTypes.XORM_MODEL_CALLABLES_SET.find(goCallExpr, false);
|
||||
if (descriptor == null) continue;
|
||||
|
||||
Integer argumentIndex = XormTypes.XORM_MODEL_CALLABLES.get(descriptor);
|
||||
|
||||
System.out.println("argumentIndex " + argumentIndex);
|
||||
System.out.println("getExpressionList " + goCallExpr.getArgumentList().getExpressionList().get(argumentIndex));
|
||||
|
||||
GoExpression argument = goCallExpr.getArgumentList().getExpressionList().get(argumentIndex);
|
||||
|
||||
if (argument instanceof GoUnaryExpr goUnaryExpr) {
|
||||
if (goUnaryExpr.getExpression() instanceof GoCompositeLit goCompositeLit) {
|
||||
if (goCompositeLit.getTypeReferenceExpression() == null) continue;
|
||||
schema = goCompositeLit.getTypeReferenceExpression().getIdentifier().getText();
|
||||
} else if (goUnaryExpr.getExpression() instanceof GoReferenceExpression goReferenceExpression) {
|
||||
GoVarDefinition goVarDefinition = (GoVarDefinition) goReferenceExpression.resolve();
|
||||
|
||||
if (goVarDefinition == null) continue;
|
||||
|
||||
GoType goType = goVarDefinition.getGoType(ResolveState.initial());
|
||||
if (goType == null || goType.getTypeReferenceExpression() == null) continue;
|
||||
|
||||
schema = goType.getTypeReferenceExpression().getIdentifier().getText();
|
||||
}
|
||||
} else if (argument instanceof GoBuiltinCallExpr goBuiltinCallExpr) {
|
||||
GoType goType = PsiTreeUtil.findChildOfType(goBuiltinCallExpr, GoType.class);
|
||||
if (goType == null || goType.getTypeReferenceExpression() == null) continue;
|
||||
schema = goType.getTypeReferenceExpression().getIdentifier().getText();
|
||||
} else if (argument instanceof GoReferenceExpression goReferenceExpression && goReferenceExpression.resolve() instanceof GoVarDefinition goVarDefinition) {
|
||||
GoType goType = PsiTreeUtil.findChildOfType(goVarDefinition.getParent(), GoType.class);
|
||||
if (goType != null) {
|
||||
if (goType.getTypeReferenceExpression() == null) continue;
|
||||
schema = goType.getTypeReferenceExpression().getIdentifier().getText();
|
||||
} else {
|
||||
GoCompositeLit goCompositeLit = PsiTreeUtil.findChildOfType(goVarDefinition.getParent(), GoCompositeLit.class);
|
||||
if (goCompositeLit == null || goCompositeLit.getTypeReferenceExpression() == null) continue;
|
||||
schema = goCompositeLit.getTypeReferenceExpression().getIdentifier().getText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
||||
private static @NotNull List<Tag> parseTag(String tagStr) {
|
||||
tagStr = tagStr.trim();
|
||||
boolean inQuote = false;
|
||||
boolean inBigQuote = false;
|
||||
int lastIdx = 0;
|
||||
Tag curTag = null;
|
||||
int paramStart = 0;
|
||||
List<Tag> tags = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < tagStr.length(); i++) {
|
||||
char t = tagStr.charAt(i);
|
||||
switch (t) {
|
||||
case '\'' -> inQuote = !inQuote;
|
||||
case ' ' -> {
|
||||
if (!inQuote && !inBigQuote) {
|
||||
if (lastIdx < i) {
|
||||
if (curTag == null || curTag.getName().isEmpty()) {
|
||||
curTag = new Tag(tagStr.substring(lastIdx, i), new ArrayList<>());
|
||||
}
|
||||
tags.add(curTag);
|
||||
lastIdx = i + 1;
|
||||
curTag = null;
|
||||
} else if (lastIdx == i) {
|
||||
lastIdx = i + 1;
|
||||
}
|
||||
} else if (inBigQuote && !inQuote) {
|
||||
paramStart = i + 1;
|
||||
}
|
||||
}
|
||||
case ',' -> {
|
||||
if (!inQuote && !inBigQuote) {
|
||||
throw new IllegalArgumentException("Comma[" + i + "] of " + tagStr + " should be in quote or big quote");
|
||||
}
|
||||
if (!inQuote) {
|
||||
curTag.getParams().add(tagStr.substring(paramStart, i).trim());
|
||||
paramStart = i + 1;
|
||||
}
|
||||
}
|
||||
case '(' -> {
|
||||
inBigQuote = true;
|
||||
if (!inQuote) {
|
||||
curTag = new Tag(tagStr.substring(lastIdx, i), new ArrayList<>());
|
||||
paramStart = i + 1;
|
||||
}
|
||||
}
|
||||
case ')' -> {
|
||||
inBigQuote = false;
|
||||
if (!inQuote) {
|
||||
curTag.getParams().add(tagStr.substring(paramStart, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lastIdx < tagStr.length()) {
|
||||
if (curTag == null || curTag.getName().isEmpty()) {
|
||||
curTag = new Tag(tagStr.substring(lastIdx), new ArrayList<>());
|
||||
}
|
||||
tags.add(curTag);
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.github.maiqingqiang.goormhelper.orm.xorm.completion;
|
||||
|
||||
import com.github.maiqingqiang.goormhelper.orm.xorm.XormTypes;
|
||||
import com.goide.GoParserDefinition;
|
||||
import com.goide.psi.GoCallExpr;
|
||||
import com.intellij.codeInsight.completion.CompletionContributor;
|
||||
import com.intellij.codeInsight.completion.CompletionType;
|
||||
import com.intellij.patterns.PlatformPatterns;
|
||||
import com.intellij.patterns.PsiElementPattern;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class XormCompletionContributor extends CompletionContributor {
|
||||
public XormCompletionContributor() {
|
||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement()
|
||||
.withElementType(GoParserDefinition.Lazy.STRING_LITERALS)
|
||||
.withSuperParent(3, new PsiElementPattern.Capture<>(GoCallExpr.class) {
|
||||
@Override
|
||||
public boolean accepts(@Nullable Object o, ProcessingContext context) {
|
||||
return o instanceof GoCallExpr && XormTypes.XORM_CALLABLES_SET.find((GoCallExpr) o, false) != null;
|
||||
}
|
||||
}),
|
||||
new XormColumnCompletionProvider());
|
||||
|
||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement()
|
||||
.withElementType(GoParserDefinition.Lazy.STRING_LITERALS)
|
||||
.withSuperParent(7, new PsiElementPattern.Capture<>(GoCallExpr.class) {
|
||||
@Override
|
||||
public boolean accepts(@Nullable Object o, ProcessingContext context) {
|
||||
return o instanceof GoCallExpr && XormTypes.XORM_CALLABLES_SET.find((GoCallExpr) o, false) != null;
|
||||
}
|
||||
}),
|
||||
new XormColumnCompletionProvider());
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.github.maiqingqiang.goormhelper.orm.xorm.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionParameters;
|
||||
import com.intellij.codeInsight.completion.CompletionProvider;
|
||||
import com.intellij.codeInsight.completion.CompletionResultSet;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class XormTagCompletionProvider extends CompletionProvider<CompletionParameters> {
|
||||
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,156 @@
|
||||
package com.github.maiqingqiang.goormhelper.services;
|
||||
|
||||
import com.github.maiqingqiang.goormhelper.bean.ScannedPath;
|
||||
import com.goide.GoFileType;
|
||||
import com.goide.psi.GoFile;
|
||||
import com.goide.psi.GoNamedSignatureOwner;
|
||||
import com.goide.psi.GoStructType;
|
||||
import com.goide.psi.GoTypeSpec;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.Service;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.SimpleModificationTracker;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.serviceContainer.NonInjectable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
@State(name = "GoORMHelper", storages = @Storage(value = "goORMHelper.xml"))
|
||||
public class GoORMHelperManager implements PersistentStateComponent<GoORMHelperManager.State> {
|
||||
|
||||
private State state;
|
||||
|
||||
private final Project project;
|
||||
|
||||
|
||||
public GoORMHelperManager(@NotNull Project project) {
|
||||
this(project, new State());
|
||||
}
|
||||
|
||||
@NonInjectable
|
||||
private GoORMHelperManager(@NotNull Project project, State state) {
|
||||
this.state = state;
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
public static GoORMHelperManager getInstance(@NotNull Project project) {
|
||||
return project.getService(GoORMHelperManager.class);
|
||||
}
|
||||
|
||||
public void addSchemaMapping(String key, @NotNull VirtualFile file) {
|
||||
String fileUrl = file.getUrl();
|
||||
|
||||
if (this.state.schemaMapping.containsKey(key)) {
|
||||
this.state.schemaMapping.get(key).add(fileUrl);
|
||||
} else {
|
||||
List<String> list = new ArrayList<>();
|
||||
list.add(fileUrl);
|
||||
this.state.schemaMapping.put(key, list);
|
||||
}
|
||||
}
|
||||
|
||||
public void addScannedPathMapping(@NotNull VirtualFile file, List<String> structList) {
|
||||
ScannedPath scanned = new ScannedPath();
|
||||
scanned.setSchema(structList);
|
||||
scanned.setLastModified(file.getTimeStamp());
|
||||
this.state.scannedPathMapping.put(file.getUrl(), scanned);
|
||||
}
|
||||
|
||||
public ScannedPath getScannedPath(@NotNull VirtualFile file) {
|
||||
return this.state.scannedPathMapping.get(file.getUrl());
|
||||
}
|
||||
|
||||
public void removeScannedPath(@NotNull VirtualFile file) {
|
||||
this.state.scannedPathMapping.remove(file.getUrl());
|
||||
}
|
||||
|
||||
public void clearScanned(@NotNull VirtualFile file) {
|
||||
ScannedPath scannedPath = getScannedPath(file);
|
||||
for (String s : scannedPath.getSchema()) {
|
||||
this.state.schemaMapping.remove(s);
|
||||
}
|
||||
removeScannedPath(file);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.state.scannedPathMapping.clear();
|
||||
this.state.schemaMapping.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable State getState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(@NotNull State state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void parseGoFile(@NotNull VirtualFile file) {
|
||||
if (!(file.isValid() && file.getName().endsWith('.' + GoFileType.DEFAULT_EXTENSION))) return;
|
||||
|
||||
DumbService.getInstance(project).runWhenSmart(() -> {
|
||||
Document document = FileDocumentManager.getInstance().getDocument(file);
|
||||
|
||||
if (document != null && PsiManager.getInstance(project).findFile(file) instanceof GoFile goFile) {
|
||||
|
||||
List<String> structList = new ArrayList<>();
|
||||
|
||||
for (GoTypeSpec typeSpec : goFile.getTypes()) {
|
||||
if (!(typeSpec.getSpecType().getType() instanceof GoStructType)) continue;
|
||||
|
||||
String structName = typeSpec.getName();
|
||||
|
||||
addSchemaMapping(typeSpec.getName(), file);
|
||||
structList.add(structName);
|
||||
}
|
||||
|
||||
addScannedPathMapping(file, structList);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void scanProject(VirtualFile virtualFile) {
|
||||
for (VirtualFile file : virtualFile.getChildren()) {
|
||||
if (!file.isValid()) continue;
|
||||
|
||||
if (file.isDirectory()) {
|
||||
scanProject(file);
|
||||
} else {
|
||||
parseGoFile(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void scan() {
|
||||
GoORMHelperProjectSettings.State state = Objects.requireNonNull(GoORMHelperProjectSettings.getInstance(project).getState());
|
||||
|
||||
if (state.enableGlobalScan) {
|
||||
scanProject(project.getBaseDir());
|
||||
} else {
|
||||
for (String path : state.scanPathList) {
|
||||
VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(path);
|
||||
if (file == null) continue;
|
||||
scanProject(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class State extends SimpleModificationTracker {
|
||||
public final Map<String, List<String>> schemaMapping = new HashMap<>();
|
||||
|
||||
public final Map<String, ScannedPath> scannedPathMapping = new HashMap<>();
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package com.github.maiqingqiang.goormhelper.services;
|
||||
|
||||
import com.github.maiqingqiang.goormhelper.Types;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.Service;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.SimpleModificationTracker;
|
||||
import com.intellij.serviceContainer.NonInjectable;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
@State(name = "GoORMHelperProjectSettings", storages = @Storage("goORMHelperSettings.xml"))
|
||||
public final class GoORMHelperProjectSettings implements PersistentStateComponent<GoORMHelperProjectSettings.State> {
|
||||
|
||||
private State state;
|
||||
private final Project project;
|
||||
|
||||
public GoORMHelperProjectSettings(@NotNull Project project) {
|
||||
this(project, new State());
|
||||
}
|
||||
|
||||
@NonInjectable
|
||||
private GoORMHelperProjectSettings(@NotNull Project project, State state) {
|
||||
this.state = state;
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
public static GoORMHelperProjectSettings getInstance(Project project) {
|
||||
return project.getService(GoORMHelperProjectSettings.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(@NotNull GoORMHelperProjectSettings.State state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void setDefaultORM(Types.ORM orm) {
|
||||
state.defaultORM = orm;
|
||||
}
|
||||
|
||||
public void setDefaultDatabase(Types.Database database) {
|
||||
state.defaultDatabase = database;
|
||||
}
|
||||
|
||||
public void setEnableGlobalScan(boolean enable) {
|
||||
state.enableGlobalScan = enable;
|
||||
}
|
||||
|
||||
public void setScanPathList(List<String> scanPathList) {
|
||||
state.scanPathList = scanPathList;
|
||||
}
|
||||
|
||||
public void setSQLPath(String customTableCompletion) {
|
||||
state.sqlPath = customTableCompletion;
|
||||
}
|
||||
|
||||
public static class State extends SimpleModificationTracker {
|
||||
public Types.ORM defaultORM = Types.ORM.AskEveryTime;
|
||||
public Types.Database defaultDatabase = Types.Database.AskEveryTime;
|
||||
public boolean enableGlobalScan = true;
|
||||
public List<String> scanPathList = new SmartList<>();
|
||||
|
||||
public String sqlPath = "";
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.github.maiqingqiang.goormhelper.sql2struct;
|
||||
|
||||
public interface ISQL2Struct {
|
||||
String convert();
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.github.maiqingqiang.goormhelper.sql2struct.impl;
|
||||
|
||||
import com.alibaba.druid.DbType;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
|
||||
import com.github.maiqingqiang.goormhelper.utils.Strings;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SQL2GormStruct extends SQL2Struct {
|
||||
public SQL2GormStruct(String sql, DbType dbType) {
|
||||
super(sql, dbType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateORMTag(@NotNull StringBuilder stringBuilder, @NotNull SQLColumnDefinition definition) {
|
||||
stringBuilder.append("gorm:\"")
|
||||
.append("column:").append(getColumn(definition)).append(";")
|
||||
.append("type:").append(getDBType(definition)).append(";")
|
||||
.append("comment:").append(getComment(definition)).append(";");
|
||||
|
||||
if (definition.isPrimaryKey()) {
|
||||
stringBuilder.append("primaryKey;");
|
||||
}
|
||||
|
||||
if (definition.containsNotNullConstaint()) {
|
||||
stringBuilder.append("not null;");
|
||||
}
|
||||
|
||||
if (definition.getDefaultExpr() != null) {
|
||||
String def = Strings.clearSingleQuotn(definition.getDefaultExpr().toString());
|
||||
|
||||
if (!def.isEmpty()) {
|
||||
stringBuilder.append("default:").append(def).append(";");
|
||||
}
|
||||
}
|
||||
|
||||
stringBuilder.append("\" ");
|
||||
}
|
||||
}
|
@ -0,0 +1,153 @@
|
||||
package com.github.maiqingqiang.goormhelper.sql2struct.impl;
|
||||
|
||||
import com.alibaba.druid.DbType;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableElement;
|
||||
import com.github.maiqingqiang.goormhelper.sql2struct.ISQL2Struct;
|
||||
import com.github.maiqingqiang.goormhelper.utils.Strings;
|
||||
import com.google.common.base.CaseFormat;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class SQL2Struct implements ISQL2Struct {
|
||||
private final String sql;
|
||||
private final DbType dbType;
|
||||
|
||||
private static final Map<String, String> dataType = Map.ofEntries(
|
||||
Map.entry("numeric", "int32"),
|
||||
Map.entry("integer", "int32"),
|
||||
Map.entry("int", "int32"),
|
||||
Map.entry("smallint", "int32"),
|
||||
Map.entry("mediumint", "int32"),
|
||||
Map.entry("tinyint", "int32"),
|
||||
Map.entry("bigint", "int64"),
|
||||
Map.entry("float", "float32"),
|
||||
Map.entry("real", "float64"),
|
||||
Map.entry("double", "float64"),
|
||||
Map.entry("decimal", "float64"),
|
||||
Map.entry("char", "string"),
|
||||
Map.entry("varchar", "string"),
|
||||
Map.entry("tinytext", "string"),
|
||||
Map.entry("mediumtext", "string"),
|
||||
Map.entry("longtext", "string"),
|
||||
Map.entry("binary", "[]byte"),
|
||||
Map.entry("varbinary", "[]byte"),
|
||||
Map.entry("tinyblob", "[]byte"),
|
||||
Map.entry("blob", "[]byte"),
|
||||
Map.entry("mediumblob", "[]byte"),
|
||||
Map.entry("longblob", "[]byte"),
|
||||
Map.entry("text", "string"),
|
||||
Map.entry("json", "string"),
|
||||
Map.entry("enum", "string"),
|
||||
Map.entry("time", "time.Time"),
|
||||
Map.entry("date", "time.Time"),
|
||||
Map.entry("datetime", "time.Time"),
|
||||
Map.entry("timestamp", "time.Time"),
|
||||
Map.entry("year", "int32"),
|
||||
Map.entry("bit", "[]uint8"),
|
||||
Map.entry("boolean", "bool")
|
||||
);
|
||||
|
||||
private static final String defaultDataType = "string";
|
||||
|
||||
|
||||
public SQL2Struct(String sql, DbType dbType) {
|
||||
this.sql = sql;
|
||||
this.dbType = dbType;
|
||||
}
|
||||
|
||||
public String convert() {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
List<SQLStatement> statementList = SQLUtils.parseStatements(sql, dbType);
|
||||
|
||||
for (SQLStatement statement : statementList) {
|
||||
singleConvert(stringBuilder, statement);
|
||||
}
|
||||
|
||||
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
private void singleConvert(@NotNull StringBuilder stringBuilder, SQLStatement statement) {
|
||||
SQLCreateTableStatement createTableStatement = (SQLCreateTableStatement) statement;
|
||||
|
||||
String tableName = Strings.clearQuote(createTableStatement.getTableName());
|
||||
tableName = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName);
|
||||
|
||||
stringBuilder.append("type ").append(tableName).append(" struct {\n");
|
||||
|
||||
|
||||
List<SQLTableElement> tableElementList = createTableStatement.getTableElementList();
|
||||
|
||||
for (SQLTableElement sqlTableElement : tableElementList) {
|
||||
if (sqlTableElement instanceof SQLColumnDefinition sqlColumnDefinition) {
|
||||
generateStructField(stringBuilder, sqlColumnDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
stringBuilder.append("}\n\n");
|
||||
}
|
||||
|
||||
private String getGoType(String type) {
|
||||
return dataType.getOrDefault(type, defaultDataType);
|
||||
}
|
||||
|
||||
protected String getGoType(@NotNull SQLColumnDefinition definition) {
|
||||
return getGoType(definition.getDataType().getName());
|
||||
}
|
||||
|
||||
protected void generateStructField(@NotNull StringBuilder stringBuilder, @NotNull SQLColumnDefinition definition) {
|
||||
stringBuilder.append("\t")
|
||||
.append(getField(definition))
|
||||
.append(" ")
|
||||
.append(getGoType(definition))
|
||||
.append(" ");
|
||||
|
||||
generateStructTags(stringBuilder, definition);
|
||||
|
||||
stringBuilder.append("// ")
|
||||
.append(getComment(definition))
|
||||
.append("\n");
|
||||
}
|
||||
|
||||
protected void generateStructTags(@NotNull StringBuilder stringBuilder, @NotNull SQLColumnDefinition definition) {
|
||||
stringBuilder.append("`");
|
||||
generateORMTag(stringBuilder, definition);
|
||||
generateJsonTag(stringBuilder, definition);
|
||||
stringBuilder.append("`");
|
||||
}
|
||||
|
||||
protected void generateORMTag(@NotNull StringBuilder stringBuilder, @NotNull SQLColumnDefinition definition) {
|
||||
|
||||
}
|
||||
|
||||
protected void generateJsonTag(@NotNull StringBuilder stringBuilder, @NotNull SQLColumnDefinition definition) {
|
||||
stringBuilder.append("json:\"").append(getColumn(definition)).append("\"");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected String getField(@NotNull SQLColumnDefinition definition) {
|
||||
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, getColumn(definition));
|
||||
}
|
||||
|
||||
protected String getDBType(@NotNull SQLColumnDefinition definition) {
|
||||
return definition.getDataType().toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected String getColumn(@NotNull SQLColumnDefinition definition) {
|
||||
return Strings.clearQuote(definition.getName().getSimpleName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected String getComment(@NotNull SQLColumnDefinition definition) {
|
||||
return Strings.clearSingleQuotn(definition.getComment().toString());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.github.maiqingqiang.goormhelper.sql2struct.impl;
|
||||
|
||||
import com.alibaba.druid.DbType;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
|
||||
import com.github.maiqingqiang.goormhelper.utils.Strings;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SQL2XormStruct extends SQL2Struct {
|
||||
public SQL2XormStruct(String sql, DbType dbType) {
|
||||
super(sql, dbType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateORMTag(@NotNull StringBuilder stringBuilder, @NotNull SQLColumnDefinition definition) {
|
||||
stringBuilder.append("xorm:\"");
|
||||
|
||||
stringBuilder.append(getDBType(definition)).append(" ");
|
||||
stringBuilder.append("'").append(getColumn(definition)).append("' ");
|
||||
stringBuilder.append("comment('").append(getComment(definition)).append("') ");
|
||||
|
||||
if (definition.isPrimaryKey()) {
|
||||
stringBuilder.append("pk ");
|
||||
}
|
||||
|
||||
if (definition.isAutoIncrement()){
|
||||
stringBuilder.append("autoincr ");
|
||||
}
|
||||
|
||||
if (definition.containsNotNullConstaint()) {
|
||||
stringBuilder.append("notnull ");
|
||||
}
|
||||
|
||||
if (definition.getDefaultExpr() != null) {
|
||||
String def = Strings.clearSingleQuotn(definition.getDefaultExpr().toString());
|
||||
|
||||
if (!def.isEmpty()) {
|
||||
stringBuilder.append("default ").append(def).append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
stringBuilder.append("\" ");
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.github.maiqingqiang.goormhelper.ui.ConvertSettingDialogWrapper">
|
||||
<grid id="cbd77" binding="contentPane" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="48" y="297" width="436" height="49"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="4897" class="com.intellij.openapi.ui.LabeledComponent" binding="databaseComponent">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<labelLocation value="West"/>
|
||||
<text value="选择数据库"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="7396f" class="com.intellij.openapi.ui.LabeledComponent" binding="ormComponent">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<labelLocation value="West"/>
|
||||
<text value="选择ORM"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
@ -0,0 +1,49 @@
|
||||
package com.github.maiqingqiang.goormhelper.ui;
|
||||
|
||||
import com.github.maiqingqiang.goormhelper.GoORMHelperBundle;
|
||||
import com.github.maiqingqiang.goormhelper.Types;
|
||||
import com.github.maiqingqiang.goormhelper.services.GoORMHelperProjectSettings;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.LabeledComponent;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ConvertSettingDialogWrapper extends DialogWrapper {
|
||||
private JPanel contentPane;
|
||||
|
||||
@lombok.Getter
|
||||
private LabeledComponent<JComboBox<Types.Database>> databaseComponent;
|
||||
|
||||
@lombok.Getter
|
||||
private LabeledComponent<JComboBox<Types.ORM>> ormComponent;
|
||||
|
||||
public ConvertSettingDialogWrapper(Project project) {
|
||||
super(true);
|
||||
|
||||
GoORMHelperProjectSettings.State state = Objects.requireNonNull(GoORMHelperProjectSettings.getInstance(project).getState());
|
||||
|
||||
ComboBox<Types.ORM> ormComboBox = new ComboBox<>(Types.ORM.values());
|
||||
ormComboBox.removeItem(Types.ORM.AskEveryTime);
|
||||
ormComboBox.setSelectedItem(state.defaultORM);
|
||||
|
||||
ormComponent.setComponent(ormComboBox);
|
||||
|
||||
ComboBox<Types.Database> databaseComboBox = new ComboBox<>(Types.Database.values());
|
||||
databaseComboBox.removeItem(Types.Database.AskEveryTime);
|
||||
databaseComboBox.setSelectedItem(state.defaultDatabase);
|
||||
databaseComponent.setComponent(databaseComboBox);
|
||||
|
||||
setTitle(GoORMHelperBundle.message("sql.convert.struct"));
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable JComponent createCenterPanel() {
|
||||
return contentPane;
|
||||
}
|
||||
}
|
@ -0,0 +1,158 @@
|
||||
package com.github.maiqingqiang.goormhelper.ui;
|
||||
|
||||
import com.github.maiqingqiang.goormhelper.GoORMHelperBundle;
|
||||
import com.github.maiqingqiang.goormhelper.Types;
|
||||
import com.github.maiqingqiang.goormhelper.services.GoORMHelperManager;
|
||||
import com.github.maiqingqiang.goormhelper.services.GoORMHelperProjectSettings;
|
||||
import com.intellij.openapi.fileChooser.FileChooser;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
|
||||
import com.intellij.openapi.options.ConfigurableUi;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.ToolbarDecorator;
|
||||
import com.intellij.ui.table.TableView;
|
||||
import com.intellij.util.ui.FormBuilder;
|
||||
import com.intellij.util.ui.ListTableModel;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class GoORMHelperSettingForm implements ConfigurableUi<GoORMHelperProjectSettings> {
|
||||
|
||||
private final Project project;
|
||||
private JPanel panel;
|
||||
private ComboBox<Types.ORM> ormComboBox;
|
||||
private ComboBox<Types.Database> databaseComboBox;
|
||||
private JCheckBox enableGlobalScanCheckBox;
|
||||
private ListTableModel<String> scanPathListTableModel;
|
||||
// private TextFieldWithBrowseButton sqlPathTextField;
|
||||
private TableView<String> scanPathTableView;
|
||||
|
||||
public GoORMHelperSettingForm(Project project) {
|
||||
this.project = project;
|
||||
initComponent();
|
||||
}
|
||||
|
||||
private void initComponent() {
|
||||
ormComboBox = new ComboBox<>(Types.ORM.values());
|
||||
databaseComboBox = new ComboBox<>(Types.Database.values());
|
||||
enableGlobalScanCheckBox = new JCheckBox(GoORMHelperBundle.message("setting.enableGlobalScanCheckBox.title"));
|
||||
|
||||
// sqlPathTextField = new TextFieldWithBrowseButton();
|
||||
// sqlPathTextField.addBrowseFolderListener(GoORMHelperBundle.message("setting.sqlPathTextField.title"), null, null, FileChooserDescriptorFactory.createSingleFolderDescriptor());
|
||||
|
||||
panel = FormBuilder.createFormBuilder()
|
||||
.addLabeledComponent(GoORMHelperBundle.message("setting.ormComboBox.title"), ormComboBox)
|
||||
.addLabeledComponent(GoORMHelperBundle.message("setting.databaseComboBox.title"), databaseComboBox)
|
||||
// .addLabeledComponent(GoORMHelperBundle.message("setting.sqlPathTextField.title"), sqlPathTextField)
|
||||
.addComponent(enableGlobalScanCheckBox)
|
||||
.addComponentFillVertically(initScanPathComponent(), 0)
|
||||
.getPanel();
|
||||
|
||||
|
||||
enableGlobalScanCheckBox.addChangeListener(e -> {
|
||||
scanPathTableView.setEnabled(!enableGlobalScanCheckBox.isSelected());
|
||||
});
|
||||
}
|
||||
|
||||
private @NotNull JPanel initScanPathComponent() {
|
||||
scanPathListTableModel = new ListTableModel<>(new LocationColumn(GoORMHelperBundle.message("setting.tableview.column.location")));
|
||||
scanPathTableView = new TableView<>(scanPathListTableModel);
|
||||
scanPathTableView.setStriped(true);
|
||||
scanPathTableView.setMinRowHeight(25);
|
||||
ToolbarDecorator decorator = ToolbarDecorator.createDecorator(scanPathTableView, null);
|
||||
|
||||
decorator.setAddAction(button -> {
|
||||
VirtualFile selectedFile =
|
||||
FileChooser.chooseFile(getFileChooserDescriptor(GoORMHelperBundle.message("setting.decorator.title")), project, null);
|
||||
|
||||
if (selectedFile != null) {
|
||||
scanPathListTableModel.insertRow(0, selectedFile.getUrl());
|
||||
}
|
||||
});
|
||||
|
||||
JPanel scanPathPanel = decorator.createPanel();
|
||||
|
||||
UIUtil.addBorder(scanPathPanel, IdeBorderFactory.createTitledBorder(GoORMHelperBundle.message("setting.decorator.title"), false));
|
||||
|
||||
return scanPathPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(@NotNull GoORMHelperProjectSettings settings) {
|
||||
loadSettings(settings);
|
||||
}
|
||||
|
||||
private void loadSettings(@NotNull GoORMHelperProjectSettings settings) {
|
||||
GoORMHelperProjectSettings.State state = Objects.requireNonNull(settings.getState());
|
||||
|
||||
ormComboBox.setSelectedItem(state.defaultORM);
|
||||
databaseComboBox.setSelectedItem(state.defaultDatabase);
|
||||
// sqlPathTextField.setText(state.sqlPath);
|
||||
enableGlobalScanCheckBox.setSelected(state.enableGlobalScan);
|
||||
scanPathListTableModel.setItems(state.scanPathList);
|
||||
scanPathTableView.setEnabled(!state.enableGlobalScan);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isModified(@NotNull GoORMHelperProjectSettings settings) {
|
||||
GoORMHelperProjectSettings.State state = Objects.requireNonNull(settings.getState());
|
||||
|
||||
return !(ormComboBox.getSelectedItem() == state.defaultORM
|
||||
&& databaseComboBox.getSelectedItem() == state.defaultDatabase
|
||||
// && sqlPathTextField.getText().equals(state.sqlPath)
|
||||
&& enableGlobalScanCheckBox.isSelected() == state.enableGlobalScan
|
||||
&& scanPathListTableModel.getItems().equals(state.scanPathList));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(@NotNull GoORMHelperProjectSettings settings) {
|
||||
|
||||
boolean oldEnableGlobalScan = Objects.requireNonNull(settings.getState()).enableGlobalScan;
|
||||
List<String> oldscanPathList = scanPathListTableModel.getItems();
|
||||
|
||||
settings.setDefaultDatabase((Types.Database) databaseComboBox.getSelectedItem());
|
||||
settings.setDefaultORM((Types.ORM) ormComboBox.getSelectedItem());
|
||||
settings.setEnableGlobalScan(enableGlobalScanCheckBox.isSelected());
|
||||
settings.setScanPathList(scanPathListTableModel.getItems());
|
||||
// settings.setSQLPath(sqlPathTextField.getText());
|
||||
|
||||
if (oldEnableGlobalScan != enableGlobalScanCheckBox.isSelected() || !oldscanPathList.equals(scanPathListTableModel.getItems())) {
|
||||
GoORMHelperManager goORMHelperManager = GoORMHelperManager.getInstance(project);
|
||||
goORMHelperManager.clear();
|
||||
goORMHelperManager.scan();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull JComponent getComponent() {
|
||||
return panel;
|
||||
}
|
||||
|
||||
private static FileChooserDescriptor getFileChooserDescriptor(@NlsContexts.DialogTitle String title) {
|
||||
FileChooserDescriptor descriptor = new FileChooserDescriptor(true, true, false, false, false, true)
|
||||
.withShowFileSystemRoots(true)
|
||||
.withShowHiddenFiles(true);
|
||||
|
||||
if (title != null) {
|
||||
descriptor.setTitle(title);
|
||||
}
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.github.maiqingqiang.goormhelper.ui;
|
||||
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public interface Icons {
|
||||
Icon Gorm35x12 = IconLoader.getIcon("icons/gorm35x12.svg", Icons.class);
|
||||
Icon Xorm19x12 = IconLoader.getIcon("icons/xorm19x12.svg", Icons.class);
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package com.github.maiqingqiang.goormhelper.ui;
|
||||
|
||||
import com.goide.GoFileType;
|
||||
import com.goide.GoIcons;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import com.intellij.util.ui.ColumnInfo;
|
||||
import com.intellij.util.ui.table.IconTableCellRenderer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
|
||||
public class LocationColumn extends ColumnInfo<String, String> {
|
||||
|
||||
public LocationColumn(@NlsContexts.ColumnName String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String valueOf(String s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable TableCellRenderer getRenderer(String s) {
|
||||
return new IconTableCellRenderer<String>() {
|
||||
@Override
|
||||
protected @Nullable Icon getIcon(@NotNull String value, JTable table, int row) {
|
||||
VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(value);
|
||||
if (file != null) {
|
||||
if (file.isDirectory()) {
|
||||
return PlatformIcons.FOLDER_ICON;
|
||||
} else if (file.getPath().endsWith('.' + GoFileType.DEFAULT_EXTENSION)) {
|
||||
return GoIcons.ICON;
|
||||
}
|
||||
}
|
||||
return AllIcons.General.Error;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setValue(Object value) {
|
||||
String url = (String) value;
|
||||
VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url);
|
||||
if ((file == null)) {
|
||||
setForeground(JBColor.RED);
|
||||
}
|
||||
setText(file != null ? file.getPresentableUrl() : url);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.github.maiqingqiang.goormhelper.ui;
|
||||
|
||||
import com.github.maiqingqiang.goormhelper.GoORMHelperBundle;
|
||||
import com.github.maiqingqiang.goormhelper.services.GoORMHelperProjectSettings;
|
||||
import com.github.maiqingqiang.goormhelper.ui.GoORMHelperSettingForm;
|
||||
import com.intellij.openapi.options.ConfigurableBase;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SettingConfigurable extends ConfigurableBase<GoORMHelperSettingForm, GoORMHelperProjectSettings> {
|
||||
|
||||
private static final String ID = "go.orm.helper";
|
||||
private final Project project;
|
||||
|
||||
public SettingConfigurable(Project project) {
|
||||
super(ID, GoORMHelperBundle.message("name"), null);
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull GoORMHelperProjectSettings getSettings() {
|
||||
return GoORMHelperProjectSettings.getInstance(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GoORMHelperSettingForm createUi() {
|
||||
return new GoORMHelperSettingForm(project);
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.github.maiqingqiang.goormhelper.utils;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
|
||||
public class CacheManager {
|
||||
private static volatile CacheManager instance;
|
||||
private static final Object monitor = new Object();
|
||||
private final Cache<String, Object> cache = Caffeine.newBuilder().build();
|
||||
|
||||
private CacheManager() {
|
||||
}
|
||||
|
||||
public void put(String cacheKey, Object value) {
|
||||
cache.put(cacheKey, value);
|
||||
}
|
||||
|
||||
public Object get(String cacheKey) {
|
||||
return cache.getIfPresent(cacheKey);
|
||||
}
|
||||
|
||||
public void clear(String cacheKey) {
|
||||
cache.put(cacheKey, null);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
cache.cleanUp();
|
||||
}
|
||||
|
||||
public static CacheManager getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (monitor) {
|
||||
if (instance == null) {
|
||||
instance = new CacheManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package com.github.maiqingqiang.goormhelper.utils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class Strings {
|
||||
|
||||
// https://github.com/golang/lint/blob/master/lint.go#L770
|
||||
public static final Map<String, String> COMMON_INITIALISMS = Map.ofEntries(
|
||||
Map.entry("ACL", "acl"),
|
||||
Map.entry("API", "api"),
|
||||
Map.entry("ASCII", "ascii"),
|
||||
Map.entry("CPU", "cpu"),
|
||||
Map.entry("CSS", "css"),
|
||||
Map.entry("DNS", "dns"),
|
||||
Map.entry("EOF", "eof"),
|
||||
Map.entry("GUID", "guid"),
|
||||
Map.entry("HTML", "html"),
|
||||
Map.entry("HTTP", "http"),
|
||||
Map.entry("HTTPS", "https"),
|
||||
Map.entry("ID", "id"),
|
||||
Map.entry("IP", "ip"),
|
||||
Map.entry("JSON", "json"),
|
||||
Map.entry("LHS", "lhs"),
|
||||
Map.entry("QPS", "qps"),
|
||||
Map.entry("RAM", "ram"),
|
||||
Map.entry("RHS", "rhs"),
|
||||
Map.entry("RPC", "rpc"),
|
||||
Map.entry("SLA", "sla"),
|
||||
Map.entry("SMTP", "smtp"),
|
||||
Map.entry("SQL", "sql"),
|
||||
Map.entry("SSH", "ssh"),
|
||||
Map.entry("TCP", "tcp"),
|
||||
Map.entry("TLS", "tls"),
|
||||
Map.entry("TTL", "ttl"),
|
||||
Map.entry("UDP", "udp"),
|
||||
Map.entry("UI", "ui"),
|
||||
Map.entry("UID", "uid"),
|
||||
Map.entry("UUID", "uuid"),
|
||||
Map.entry("URI", "uri"),
|
||||
Map.entry("URL", "url"),
|
||||
Map.entry("UTF8", "utf8"),
|
||||
Map.entry("VM", "vm"),
|
||||
Map.entry("XML", "xml")
|
||||
);
|
||||
|
||||
|
||||
public static String replaceCommonInitialisms(String s) {
|
||||
for (Map.Entry<String, String> entry : COMMON_INITIALISMS.entrySet()) {
|
||||
s = s.replaceAll(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
public static String clearQuote(String s) {
|
||||
if (s.startsWith("`") && s.endsWith("`")) {
|
||||
return s.substring(1, s.length() - 1);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public static String clearSingleQuotn(String s) {
|
||||
if (s.startsWith("'") && s.endsWith("'")) {
|
||||
return s.substring(1, s.length() - 1);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package org.jetbrains.plugins.template.listeners
|
||||
|
||||
import com.intellij.openapi.application.ApplicationActivationListener
|
||||
import com.intellij.openapi.diagnostic.thisLogger
|
||||
import com.intellij.openapi.wm.IdeFrame
|
||||
|
||||
internal class MyApplicationActivationListener : ApplicationActivationListener {
|
||||
|
||||
override fun applicationActivated(ideFrame: IdeFrame) {
|
||||
thisLogger().warn("Don't forget to remove all non-needed sample code files with their corresponding registration entries in `plugin.xml`.")
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package org.jetbrains.plugins.template.services
|
||||
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.diagnostic.thisLogger
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.plugins.template.MyBundle
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
class MyProjectService(project: Project) {
|
||||
|
||||
init {
|
||||
thisLogger().info(MyBundle.message("projectService", project.name))
|
||||
thisLogger().warn("Don't forget to remove all non-needed sample code files with their corresponding registration entries in `plugin.xml`.")
|
||||
}
|
||||
|
||||
fun getRandomNumber() = (1..100).random()
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package org.jetbrains.plugins.template.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 org.jetbrains.plugins.template.MyBundle
|
||||
import org.jetbrains.plugins.template.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`.")
|
||||
}
|
||||
|
||||
override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
|
||||
val myToolWindow = MyToolWindow(toolWindow)
|
||||
val content = ContentFactory.getInstance().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<MyProjectService>()
|
||||
|
||||
fun getContent() = JBPanel<JBPanel<*>>().apply {
|
||||
val label = JBLabel(MyBundle.message("randomLabel", "?"))
|
||||
|
||||
add(label)
|
||||
add(JButton(MyBundle.message("shuffle")).apply {
|
||||
addActionListener {
|
||||
label.text = MyBundle.message("randomLabel", service.getRandomNumber())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
@ -1,18 +1,53 @@
|
||||
<!-- Plugin Configuration File. Read more: https://plugins.jetbrains.com/docs/intellij/plugin-configuration-file.html -->
|
||||
<idea-plugin>
|
||||
<id>org.jetbrains.plugins.template</id>
|
||||
<name>IntelliJ Platform Plugin Template</name>
|
||||
<vendor>JetBrains</vendor>
|
||||
<id>com.github.maiqingqiang.goormhelper</id>
|
||||
<name>Go ORM Helper</name>
|
||||
<vendor>John Mai</vendor>
|
||||
|
||||
<depends>com.intellij.modules.platform</depends>
|
||||
<depends>com.intellij.modules.go</depends>
|
||||
<depends>org.jetbrains.plugins.go</depends>
|
||||
|
||||
<resource-bundle>messages.MyBundle</resource-bundle>
|
||||
<resource-bundle>messages.GoORMHelperBundle</resource-bundle>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<toolWindow factoryClass="org.jetbrains.plugins.template.toolWindow.MyToolWindowFactory" id="MyToolWindow"/>
|
||||
<projectService serviceImplementation="com.github.maiqingqiang.goormhelper.services.GoORMHelperManager"/>
|
||||
<projectService
|
||||
serviceImplementation="com.github.maiqingqiang.goormhelper.services.GoORMHelperProjectSettings"/>
|
||||
|
||||
<completion.contributor language="go"
|
||||
implementationClass="com.github.maiqingqiang.goormhelper.orm.gorm.codeInsights.completion.GormCompletionContributor"/>
|
||||
|
||||
<completion.contributor language="go"
|
||||
implementationClass="com.github.maiqingqiang.goormhelper.orm.xorm.completion.XormCompletionContributor"/>
|
||||
|
||||
<highlightVisitor
|
||||
implementation="com.github.maiqingqiang.goormhelper.codeInsights.GoORMHelperHighlightVisitor"/>
|
||||
|
||||
<editorActionHandler action="EditorPaste"
|
||||
implementationClass="com.github.maiqingqiang.goormhelper.actions.EditorPasteListener"
|
||||
order="first"/>
|
||||
|
||||
<projectConfigurable
|
||||
parentId="tools"
|
||||
instance="com.github.maiqingqiang.goormhelper.ui.SettingConfigurable"
|
||||
displayName="Go ORM Helper"/>
|
||||
</extensions>
|
||||
|
||||
<applicationListeners>
|
||||
<listener class="org.jetbrains.plugins.template.listeners.MyApplicationActivationListener" topic="com.intellij.openapi.application.ApplicationActivationListener"/>
|
||||
</applicationListeners>
|
||||
<extensions defaultExtensionNs="com.goide">
|
||||
|
||||
</extensions>
|
||||
|
||||
<projectListeners>
|
||||
<listener class="com.github.maiqingqiang.goormhelper.listeners.MyProjectManagerListener"
|
||||
topic="com.intellij.openapi.project.ProjectManagerListener"/>
|
||||
<listener class="com.github.maiqingqiang.goormhelper.listeners.SchemaFileListener"
|
||||
topic="com.intellij.openapi.vfs.newvfs.BulkFileListener"/>
|
||||
</projectListeners>
|
||||
|
||||
<actions>
|
||||
<action class="com.github.maiqingqiang.goormhelper.actions.SQL2StructAction" text="SQL2Struct">
|
||||
<add-to-group group-id="EditorPopupMenu" anchor="first"/>
|
||||
</action>
|
||||
</actions>
|
||||
</idea-plugin>
|
||||
|
Before Width: | Height: | Size: 795 B After Width: | Height: | Size: 1.4 MiB |
After Width: | Height: | Size: 131 KiB |
After Width: | Height: | Size: 1.4 MiB |
After Width: | Height: | Size: 1.4 MiB |
After Width: | Height: | Size: 1.4 MiB |
After Width: | Height: | Size: 1.4 MiB |
After Width: | Height: | Size: 11 KiB |
@ -0,0 +1,17 @@
|
||||
name=Go ORM Helper
|
||||
# intializing
|
||||
initializing.title=Intializing go ORM helper
|
||||
# convert struct
|
||||
sql.convert.struct=SQL Convert Struct
|
||||
# setting
|
||||
setting.tableview.column.location=Location
|
||||
setting.decorator.title=Scan Path
|
||||
setting.ormComboBox.title=ORM
|
||||
setting.databaseComboBox.title=Database
|
||||
setting.sqlPathTextField.title=SQL File Path
|
||||
setting.enableGlobalScanCheckBox.title=Global Scan
|
||||
# database
|
||||
database.AskEveryTime=Ask every time
|
||||
# orm
|
||||
orm.AskEveryTime=Ask every time
|
||||
orm.General=General
|
@ -1,39 +0,0 @@
|
||||
package org.jetbrains.plugins.template
|
||||
|
||||
import com.intellij.ide.highlighter.XmlFileType
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.psi.xml.XmlFile
|
||||
import com.intellij.testFramework.TestDataPath
|
||||
import com.intellij.testFramework.fixtures.BasePlatformTestCase
|
||||
import com.intellij.util.PsiErrorElementUtil
|
||||
import org.jetbrains.plugins.template.services.MyProjectService
|
||||
|
||||
@TestDataPath("\$CONTENT_ROOT/src/test/testData")
|
||||
class MyPluginTest : BasePlatformTestCase() {
|
||||
|
||||
fun testXMLFile() {
|
||||
val psiFile = myFixture.configureByText(XmlFileType.INSTANCE, "<foo>bar</foo>")
|
||||
val xmlFile = assertInstanceOf(psiFile, XmlFile::class.java)
|
||||
|
||||
assertFalse(PsiErrorElementUtil.hasErrors(project, xmlFile.virtualFile))
|
||||
|
||||
assertNotNull(xmlFile.rootTag)
|
||||
|
||||
xmlFile.rootTag?.let {
|
||||
assertEquals("foo", it.name)
|
||||
assertEquals("bar", it.value.text)
|
||||
}
|
||||
}
|
||||
|
||||
fun testRename() {
|
||||
myFixture.testRename("foo.xml", "foo_after.xml", "a2")
|
||||
}
|
||||
|
||||
fun testProjectService() {
|
||||
val projectService = project.service<MyProjectService>()
|
||||
|
||||
assertNotSame(projectService.getRandomNumber(), projectService.getRandomNumber())
|
||||
}
|
||||
|
||||
override fun getTestDataPath() = "src/test/testData/rename"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
<root>
|
||||
<a<caret>1>Foo</a1>
|
||||
</root>
|
@ -1,3 +0,0 @@
|
||||
<root>
|
||||
<a2>Foo</a2>
|
||||
</root>
|