From 07fe8661cd61d03a3b2c4366639507d16b364680 Mon Sep 17 00:00:00 2001
From: AprilViolet
Date: Sun, 12 Sep 2021 10:11:38 +0800
Subject: [PATCH 1/2] :recycle: refactor(upgrade template to v1.0.0):
---
.github/workflows/build.yml | 177 ++++++++---------------------
.github/workflows/release.yml | 21 ++--
.github/workflows/run-ui-tests.yml | 60 ++++++++++
.gitignore | 1 +
.run/Run Plugin Tests.run.xml | 4 +-
build.gradle.kts | 73 +++++++-----
detekt-config.yml | 5 -
gradle.properties | 9 +-
qodana.yml | 6 +
9 files changed, 179 insertions(+), 177 deletions(-)
create mode 100644 .github/workflows/run-ui-tests.yml
delete mode 100644 detekt-config.yml
create mode 100644 qodana.yml
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 6fddbbb..da3618f 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -44,39 +44,52 @@ jobs:
runs-on: ubuntu-latest
steps:
+ # Check out current repository
+ - name: Fetch Sources
+ uses: actions/checkout@v2.3.4
+
# Setup Java 11 environment for the next steps
- name: Setup Java
uses: actions/setup-java@v2
with:
distribution: zulu
java-version: 11
+ cache: gradle
- # Check out current repository
- - name: Fetch Sources
- uses: actions/checkout@v2.3.4
+ # Set environment variables
+ - name: Export Properties
+ id: properties
+ shell: bash
+ run: |
+ PROPERTIES="$(./gradlew properties --console=plain -q)"
+ IDE_VERSIONS="$(echo "$PROPERTIES" | grep "^pluginVerifierIdeVersions:" | base64)"
- # Cache Gradle dependencies
- - name: Setup Gradle Dependencies Cache
- uses: actions/cache@v2.1.6
- with:
- path: ~/.gradle/caches
- key: ${{ runner.os }}-gradle-caches-${{ hashFiles('**/*.gradle', '**/*.gradle.kts', 'gradle.properties') }}
+ echo "::set-output name=ideVersions::$IDE_VERSIONS"
+ echo "::set-output name=pluginVerifierHomeDir::~/.pluginVerifier"
- # Cache Gradle Wrapper
- - name: Setup Gradle Wrapper Cache
+ # Cache Plugin Verifier IDEs
+ - name: Setup Plugin Verifier IDEs Cache
uses: actions/cache@v2.1.6
with:
- path: ~/.gradle/wrapper
- key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}
+ path: ${{ steps.properties.outputs.pluginVerifierHomeDir }}/ides
+ key: ${{ runner.os }}-plugin-verifier-${{ steps.properties.outputs.ideVersions }}
+
+ # Run Qodana inspections
+ - name: Qodana - Code Inspection
+ uses: JetBrains/qodana-action@v2.1-eap
- # Run detekt, ktlint and tests
- - name: Run Linters and Test
- run: ./gradlew check
+ # Run tests
+ - name: Run Tests
+ run: ./gradlew test
# Run verifyPlugin Gradle task
- name: Verify Plugin
run: ./gradlew verifyPlugin
+ # Run IntelliJ Plugin Verifier action using GitHub Action
+ - name: Run Plugin Verifier
+ run: ./gradlew runPluginVerifier -Pplugin.verifier.home.dir=${{ steps.properties.outputs.pluginVerifierHomeDir }}
+
# Build plugin with buildPlugin Gradle task and provide the artifact for the next workflow jobs
# Requires test job to be passed
build:
@@ -84,36 +97,21 @@ jobs:
needs: test
runs-on: ubuntu-latest
outputs:
- name: ${{ steps.properties.outputs.name }}
version: ${{ steps.properties.outputs.version }}
changelog: ${{ steps.properties.outputs.changelog }}
- artifact: ${{ steps.properties.outputs.artifact }}
steps:
+ # Check out current repository
+ - name: Fetch Sources
+ uses: actions/checkout@v2.3.4
+
# Setup Java 11 environment for the next steps
- name: Setup Java
uses: actions/setup-java@v2
with:
distribution: zulu
java-version: 11
-
- # Check out current repository
- - name: Fetch Sources
- uses: actions/checkout@v2.3.4
-
- # Cache Gradle Dependencies
- - name: Setup Gradle Dependencies Cache
- uses: actions/cache@v2.1.6
- with:
- path: ~/.gradle/caches
- key: ${{ runner.os }}-gradle-caches-${{ hashFiles('**/*.gradle', '**/*.gradle.kts', 'gradle.properties') }}
-
- # Cache Gradle Wrapper
- - name: Setup Gradle Wrapper Cache
- uses: actions/cache@v2.1.6
- with:
- path: ~/.gradle/wrapper
- key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}
+ cache: gradle
# Set environment variables
- name: Export Properties
@@ -127,85 +125,28 @@ jobs:
CHANGELOG="${CHANGELOG//'%'/'%25'}"
CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
- ARTIFACT="${NAME}-${VERSION}.zip"
echo "::set-output name=version::$VERSION"
echo "::set-output name=name::$NAME"
echo "::set-output name=changelog::$CHANGELOG"
- echo "::set-output name=artifact::$ARTIFACT"
# Build artifact using buildPlugin Gradle task
- name: Build Plugin
run: ./gradlew buildPlugin
- # Upload plugin artifact to make it available in the next jobs
- - name: Upload artifact
- uses: actions/upload-artifact@v2.2.3
+ # Store built plugin as an artifact for downloading
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v2.2.4
with:
- name: plugin-artifact
- path: ./build/distributions/${{ steps.properties.outputs.artifact }}
-
- # Verify built plugin using IntelliJ Plugin Verifier tool
- # Requires build job to be passed
- verify:
- name: Verify
- needs: build
- runs-on: ubuntu-latest
- steps:
-
- # Setup Java 11 environment for the next steps
- - name: Setup Java
- uses: actions/setup-java@v2
- with:
- distribution: zulu
- java-version: 11
-
- # Check out current repository
- - name: Fetch Sources
- uses: actions/checkout@v2.3.4
-
- # Cache Gradle Dependencies
- - name: Setup Gradle Dependencies Cache
- uses: actions/cache@v2.1.6
- with:
- path: ~/.gradle/caches
- key: ${{ runner.os }}-gradle-caches-${{ hashFiles('**/*.gradle', '**/*.gradle.kts', 'gradle.properties') }}
-
- # Cache Gradle Wrapper
- - name: Setup Gradle Wrapper Cache
- uses: actions/cache@v2.1.6
- with:
- path: ~/.gradle/wrapper
- key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}
-
- # Set environment variables
- - name: Export Properties
- id: properties
- shell: bash
- run: |
- PROPERTIES="$(./gradlew properties --console=plain -q)"
- IDE_VERSIONS="$(echo "$PROPERTIES" | grep "^pluginVerifierIdeVersions:" | base64)"
-
- echo "::set-output name=ideVersions::$IDE_VERSIONS"
- echo "::set-output name=pluginVerifierHomeDir::~/.pluginVerifier"
-
- # Cache Plugin Verifier IDEs
- - name: Setup Plugin Verifier IDEs Cache
- uses: actions/cache@v2.1.6
- with:
- path: ${{ steps.properties.outputs.pluginVerifierHomeDir }}/ides
- key: ${{ runner.os }}-plugin-verifier-${{ steps.properties.outputs.ideVersions }}
-
- # Run IntelliJ Plugin Verifier action using GitHub Action
- - name: Verify Plugin
- run: ./gradlew runPluginVerifier -Pplugin.verifier.home.dir=${{ steps.properties.outputs.pluginVerifierHomeDir }}
+ name: "${{ steps.properties.outputs.name }} - ${{ steps.properties.outputs.version }}"
+ path: ./build/distributions/*
# 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, verify]
+ needs: build
runs-on: ubuntu-latest
steps:
@@ -218,38 +159,16 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
- curl -H "Authorization: Bearer $GITHUB_TOKEN" https://api.github.com/repos/$GITHUB_REPOSITORY/releases \
- | tr '\r\n' ' ' \
- | jq '.[] | select(.draft == true) | .id' \
- | xargs -I '{}' \
- curl -X DELETE -H "Authorization: Bearer $GITHUB_TOKEN" https://api.github.com/repos/$GITHUB_REPOSITORY/releases/{}
+ gh api repos/{owner}/{repo}/releases \
+ --jq '.[] | select(.draft == true) | .id' \
+ | xargs -I '{}' gh api -X DELETE repos/{owner}/{repo}/releases/{}
# Create new release draft - which is not publicly visible and requires manual acceptance
- name: Create Release Draft
- id: createDraft
- uses: actions/create-release@v1.1.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- with:
- tag_name: v${{ needs.build.outputs.version }}
- release_name: v${{ needs.build.outputs.version }}
- body: ${{ needs.build.outputs.changelog }}
- draft: true
-
- # Download plugin artifact provided by the previous job
- - name: Download Artifact
- uses: actions/download-artifact@v2
- with:
- name: plugin-artifact
-
- # Upload artifact as a release asset
- - name: Upload Release Asset
- id: upload-release-asset
- uses: actions/upload-release-asset@v1.0.2
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- with:
- upload_url: ${{ steps.createDraft.outputs.upload_url }}
- asset_path: ./${{ needs.build.outputs.artifact }}
- asset_name: ${{ needs.build.outputs.artifact }}
- asset_content_type: application/zip
+ run: |
+ gh release create v${{ needs.build.outputs.version }} \
+ --draft \
+ --title "v${{ needs.build.outputs.version }}" \
+ --notes "${{ needs.build.outputs.changelog }}"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 90320b4..7ad6430 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -14,21 +14,28 @@ jobs:
runs-on: ubuntu-latest
steps:
+ # Check out current repository
+ - name: Fetch Sources
+ uses: actions/checkout@v2.3.4
+ with:
+ ref: ${{ github.event.release.tag_name }}
+
# Setup Java 11 environment for the next steps
- name: Setup Java
uses: actions/setup-java@v2
with:
distribution: zulu
java-version: 11
-
- # Check out current repository
- - name: Fetch Sources
- uses: actions/checkout@v2.3.4
- with:
- ref: ${{ github.event.release.tag_name }}
+ cache: gradle
# Publish the plugin to the Marketplace
- name: Publish Plugin
env:
PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }}
- run: ./gradlew publishPlugin
\ No newline at end of file
+ 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/*
diff --git a/.github/workflows/run-ui-tests.yml b/.github/workflows/run-ui-tests.yml
new file mode 100644
index 0000000..f549056
--- /dev/null
+++ b/.github/workflows/run-ui-tests.yml
@@ -0,0 +1,60 @@
+# GitHub Actions Workflow created for launching UI tests on Linux, Windows, and Mac in the following steps:
+# - prepare and launch Idea with your plugin and robot-server plugin, which is need to interact with UI
+# - wait for the Idea started
+# - run UI tests with separate Gradle task
+#
+# Please check https://github.com/JetBrains/intellij-ui-test-robot for information about UI tests with IntelliJ IDEA.
+#
+# 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@v2.3.4
+
+ # Setup Java 11 environment for the next steps
+ - name: Setup Java
+ uses: actions/setup-java@v2
+ with:
+ distribution: zulu
+ java-version: 11
+ 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@v1.5
+ with:
+ url: http://127.0.0.1:8082
+ max-attempts: 15
+ retry-delay: 30s
+
+ # Run tests
+ - name: Tests
+ run: ./gradlew test
diff --git a/.gitignore b/.gitignore
index 6bfa1d7..f628ad3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
.idea
.run
build
+.qodana
\ No newline at end of file
diff --git a/.run/Run Plugin Tests.run.xml b/.run/Run Plugin Tests.run.xml
index 03d0287..ae9ae13 100644
--- a/.run/Run Plugin Tests.run.xml
+++ b/.run/Run Plugin Tests.run.xml
@@ -11,7 +11,7 @@
@@ -21,4 +21,4 @@
false
-
\ No newline at end of file
+
diff --git a/build.gradle.kts b/build.gradle.kts
index 7c61815..0476faf 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,16 +1,19 @@
-import io.gitlab.arturbosch.detekt.Detekt
import org.jetbrains.changelog.markdownToHTML
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
fun properties(key: String) = project.findProperty(key).toString()
plugins {
+ // Java support
id("java")
- id("org.jetbrains.kotlin.jvm") version "1.5.20"
- id("org.jetbrains.intellij") version "1.0"
- id("org.jetbrains.changelog") version "1.1.2"
- id("io.gitlab.arturbosch.detekt") version "1.17.1"
- id("org.jlleitschuh.gradle.ktlint") version "10.0.0"
+ // Kotlin support
+ id("org.jetbrains.kotlin.jvm") version "1.5.30"
+ // Gradle IntelliJ Plugin
+ id("org.jetbrains.intellij") version "1.1.6"
+ // Gradle Changelog Plugin
+ id("org.jetbrains.changelog") version "1.3.0"
+ // Gradle Qodana Plugin
+ id("org.jetbrains.qodana") version "0.1.12"
}
group = properties("pluginGroup")
@@ -21,9 +24,6 @@ repositories {
maven(url = "https://maven.aliyun.com/repository/public")
maven(url = "https://www.jetbrains.com/intellij-repository/releases")
}
-dependencies {
- detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.17.1")
-}
intellij {
pluginName.set(properties("pluginName"))
@@ -36,33 +36,30 @@ intellij {
}
changelog {
- version = properties("pluginVersion")
- groups = emptyList()
+ version.set(properties("pluginVersion"))
+ groups.set(emptyList())
}
-detekt {
- config = files("./detekt-config.yml")
- buildUponDefaultConfig = true
-
- reports {
- html.enabled = false
- xml.enabled = false
- txt.enabled = false
- }
+qodana {
+ cachePath.set(projectDir.resolve(".qodana").canonicalPath)
+ reportPath.set(projectDir.resolve("build/reports/inspections").canonicalPath)
+ saveReport.set(true)
+ showReport.set(System.getenv("QODANA_SHOW_REPORT").toBoolean())
}
tasks {
- withType {
- sourceCompatibility = "11"
- targetCompatibility = "11"
- options.encoding = "UTF-8"
- }
- withType {
- kotlinOptions.jvmTarget = "11"
+ properties("javaVersion").let {
+ withType {
+ sourceCompatibility = it
+ targetCompatibility = it
+ }
+ withType {
+ kotlinOptions.jvmTarget = it
+ }
}
- withType {
- jvmTarget = "11"
+ wrapper {
+ gradleVersion = properties("gradleVersion")
}
patchPluginXml {
@@ -71,7 +68,7 @@ tasks {
untilBuild.set(properties("pluginUntilBuild"))
pluginDescription.set(
- File(projectDir, "README.md").readText().lines().run {
+ projectDir.resolve("README.md").readText().lines().run {
val start = ""
val end = ""
@@ -84,7 +81,21 @@ tasks {
}
runPluginVerifier {
- ideVersions.set(properties("pluginVerifierIdeVersions").split(',').map(String::trim).filter(String::isNotEmpty))
+ ideVersions.set(properties("pluginVerifierIdeVersions").split(',').map(String::trim)
+ .filter(String::isNotEmpty))
+ }
+
+ runIdeForUiTests {
+ systemProperty("robot-server.port", "8082")
+ systemProperty("ide.mac.message.dialogs.as.sheets", "false")
+ systemProperty("jb.privacy.policy.text", "")
+ systemProperty("jb.consents.confirmation.enabled", "false")
+ }
+
+ signPlugin {
+ certificateChain.set(System.getenv("CERTIFICATE_CHAIN"))
+ privateKey.set(System.getenv("PRIVATE_KEY"))
+ password.set(System.getenv("PRIVATE_KEY_PASSWORD"))
}
publishPlugin {
diff --git a/detekt-config.yml b/detekt-config.yml
deleted file mode 100644
index f69e7ca..0000000
--- a/detekt-config.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-formatting:
- Indentation:
- continuationIndentSize: 8
- ParameterListWrapping:
- indentSize: 8
diff --git a/gradle.properties b/gradle.properties
index 17e00c2..70a9562 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -2,15 +2,18 @@ pluginGroup = cn.aprilviolet.highlightbracketpair
pluginName = HighlightBracketPair
pluginVersion = 1.2.0
-pluginSinceBuild = 211
+pluginSinceBuild = 203
pluginUntilBuild = 212.*
-pluginVerifierIdeVersions = 2021.1.3, 2021.2
+pluginVerifierIdeVersions = 2020.3.4, 2021.2
-platformType = IC
+platformType = IU
platformVersion = 2021.2
platformDownloadSources = true
platformPlugins =
+javaVersion = 11
+gradleVersion = 7.2
+
kotlin.stdlib.default.dependency = false
\ No newline at end of file
diff --git a/qodana.yml b/qodana.yml
new file mode 100644
index 0000000..dac95d3
--- /dev/null
+++ b/qodana.yml
@@ -0,0 +1,6 @@
+# Qodana configuration:
+# https://www.jetbrains.com/help/qodana/qodana-yaml.html
+
+version: 1.0
+profile:
+ name: qodana.recommended
From bcd783a3feb0058fc0cc007bc240ed78cb996b83 Mon Sep 17 00:00:00 2001
From: AprilViolet
Date: Wed, 22 Sep 2021 21:00:42 +0800
Subject: [PATCH 2/2] :sparkles: feature(core): Increase XML support
---
CHANGELOG.md | 6 +
gradle.properties | 2 +-
...dapter.java => BracketMatchProcessor.java} | 89 +++------
.../adapter/BracketMatchProcessorFactory.java | 59 ++++++
.../adapter/BracketMatchProcessorHolder.java | 177 ++++++++++++++++++
.../adapter/XmlBracketMatchProcessor.java | 120 ++++++++++++
.../brace/BraceTokenTypes.java | 25 ++-
.../HighlightEditorCartListener.java | 10 +-
.../extend/CustomSupportedToken.java | 23 +++
.../extend/VueSupportedToken.java | 65 +++++++
.../extend/XmlSupportedToken.java | 135 +++++++++++++
.../AbstractBracketHighlighter.java | 58 ++++--
.../DefaultAbstractBracketHighlighter.java | 62 ++++--
.../HighlightBracketPairSettingComponent.java | 2 +-
src/main/resources/META-INF/plugin.xml | 14 +-
15 files changed, 735 insertions(+), 112 deletions(-)
rename src/main/java/cn/aprilviolet/highlightbracketpair/adapter/{BraceMatchingUtilAdapter.java => BracketMatchProcessor.java} (51%)
create mode 100644 src/main/java/cn/aprilviolet/highlightbracketpair/adapter/BracketMatchProcessorFactory.java
create mode 100644 src/main/java/cn/aprilviolet/highlightbracketpair/adapter/BracketMatchProcessorHolder.java
create mode 100644 src/main/java/cn/aprilviolet/highlightbracketpair/adapter/XmlBracketMatchProcessor.java
create mode 100644 src/main/java/cn/aprilviolet/highlightbracketpair/extend/CustomSupportedToken.java
create mode 100644 src/main/java/cn/aprilviolet/highlightbracketpair/extend/VueSupportedToken.java
create mode 100644 src/main/java/cn/aprilviolet/highlightbracketpair/extend/XmlSupportedToken.java
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a3ed7c7..88d4fb4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,12 @@
- More language support.
+## [1.3.0 - 2021.09.22]
+
+### Added
+
++ Feature:Extension enhancement for Xml.
+
## [1.2.0 - 2021.09.09]
### Added
diff --git a/gradle.properties b/gradle.properties
index 70a9562..4b72b16 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,6 +1,6 @@
pluginGroup = cn.aprilviolet.highlightbracketpair
pluginName = HighlightBracketPair
-pluginVersion = 1.2.0
+pluginVersion = 1.3.0
pluginSinceBuild = 203
pluginUntilBuild = 212.*
diff --git a/src/main/java/cn/aprilviolet/highlightbracketpair/adapter/BraceMatchingUtilAdapter.java b/src/main/java/cn/aprilviolet/highlightbracketpair/adapter/BracketMatchProcessor.java
similarity index 51%
rename from src/main/java/cn/aprilviolet/highlightbracketpair/adapter/BraceMatchingUtilAdapter.java
rename to src/main/java/cn/aprilviolet/highlightbracketpair/adapter/BracketMatchProcessor.java
index 4718fdc..7030a34 100644
--- a/src/main/java/cn/aprilviolet/highlightbracketpair/adapter/BraceMatchingUtilAdapter.java
+++ b/src/main/java/cn/aprilviolet/highlightbracketpair/adapter/BracketMatchProcessor.java
@@ -4,71 +4,45 @@
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.psi.tree.IElementType;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.Stack;
+import java.util.ArrayDeque;
+import java.util.Deque;
-import static cn.aprilviolet.highlightbracketpair.brace.BraceTokenTypes.*;
import static com.intellij.codeInsight.highlighting.BraceMatchingUtil.*;
/**
- * Brace matching util adapter.
+ * Find left and right bracket interface
*
* @author AprilViolet
- * @version V1.0.0
- * @date 2021.07.31 13:57
- * @since V1.0.0
+ * @version v1.0.0
+ * @date 2021.09.21 10:42
+ * @since v1.0.0
*/
-public class BraceMatchingUtilAdapter {
-
- public static final Set STRING_TOKEN_SET = new HashSet<>();
-
- static {
- STRING_TOKEN_SET.add(GROOVY_STRING_TOKEN);
- STRING_TOKEN_SET.add(GROOVY_SINGLE_QUOTE_TOKEN);
- STRING_TOKEN_SET.add(KOTLIN_STRING_TOKEN);
- STRING_TOKEN_SET.add(KOTLIN_CHAR_TOKEN);
- STRING_TOKEN_SET.add(JS_STRING_TOKEN);
- STRING_TOKEN_SET.add(JAVA_STRING_TOKEN);
- STRING_TOKEN_SET.add(SCALA_STRING_TOKEN);
- STRING_TOKEN_SET.add(HASKELL_STRING_TOKEN);
- }
-
- /**
- * check is the current token type is string token.
- *
- * @param tokenType token type
- * @return is string token
- */
- public static boolean isStringToken(IElementType tokenType) {
- String elementName = tokenType.toString();
- return STRING_TOKEN_SET.contains(elementName);
- }
+public interface BracketMatchProcessor {
+ Integer NON_BRACE_OFFSET = -1;
/**
* Find the left closest brace offset position.
*
- * @param iterator highlighter iterator
+ * @param iterator highlighter iterator
* @param lparenTokenType left token type to be paired
- * @param fileText file text
- * @param fileType file type
+ * @param fileText file text
+ * @param fileType file type
+ * @param isBlockCaret is it a block caret
+ * @param offset offset
* @return offset
*/
- public static int findLeftBraceOffset(HighlighterIterator iterator, IElementType lparenTokenType, CharSequence fileText,
- FileType fileType, boolean isBlockCaret) {
- int lastLeftBraceOffset = -1;
+ default int findLeftParen(HighlighterIterator iterator, IElementType lparenTokenType, CharSequence fileText,
+ FileType fileType, boolean isBlockCaret, Integer offset) {
int initOffset = iterator.atEnd() ? -1 : iterator.getStart();
-
- Stack braceStack = new Stack<>();
+ Deque braceStack = new ArrayDeque<>();
for (; !iterator.atEnd(); iterator.retreat()) {
final IElementType tokenType = iterator.getTokenType();
-
if (isLBraceToken(iterator, fileText, fileType)) {
if (!isBlockCaret && initOffset == iterator.getStart()) {
continue;
}
if (!braceStack.isEmpty()) {
- IElementType topToken = braceStack.pop();
+ IElementType topToken = braceStack.removeFirst();
if (!isPairBraces(tokenType, topToken, fileType)) {
// unmatched braces
break;
@@ -84,33 +58,34 @@ public static int findLeftBraceOffset(HighlighterIterator iterator, IElementType
if (initOffset == iterator.getStart()) {
continue;
}
- braceStack.push(iterator.getTokenType());
+ braceStack.addFirst(iterator.getTokenType());
}
}
- return lastLeftBraceOffset;
+ return NON_BRACE_OFFSET;
}
/**
* find the right closest brace offset position
*
- * @param iterator highlight iterator
+ * @param iterator highlight iterator
* @param rparenTokenType right token type to paired
- * @param fileText file text
- * @param fileType file type
+ * @param fileText file text
+ * @param fileType file type
+ * @param isBlockCaret is it a block caret
+ * @param offset offset
* @return offset
*/
- public static int findRightBraceOffset(HighlighterIterator iterator, IElementType rparenTokenType, CharSequence fileText,
- FileType fileType, boolean isBlockCaret) {
- int lastRightBraceOffset = -1;
+ default int findRightParen(HighlighterIterator iterator, IElementType rparenTokenType, CharSequence fileText,
+ FileType fileType, boolean isBlockCaret, Integer offset) {
int initOffset = iterator.atEnd() ? -1 : iterator.getStart();
- Stack braceStack = new Stack<>();
+ Deque braceStack = new ArrayDeque<>();
for (; !iterator.atEnd(); iterator.advance()) {
final IElementType tokenType = iterator.getTokenType();
if (isRBraceToken(iterator, fileText, fileType)) {
if (!braceStack.isEmpty()) {
- IElementType topToken = braceStack.pop();
+ IElementType topToken = braceStack.removeFirst();
if (!isPairBraces(tokenType, topToken, fileType)) {
// unmatched braces
break;
@@ -122,12 +97,10 @@ public static int findRightBraceOffset(HighlighterIterator iterator, IElementTyp
break;
}
}
- } else if (isLBraceToken(iterator, fileText, fileType)) {
- if (!isBlockCaret || initOffset != iterator.getStart()) {
- braceStack.push(iterator.getTokenType());
- }
+ } else if (isLBraceToken(iterator, fileText, fileType) && (!isBlockCaret || initOffset != iterator.getStart())) {
+ braceStack.addFirst(iterator.getTokenType());
}
}
- return lastRightBraceOffset;
+ return NON_BRACE_OFFSET;
}
}
diff --git a/src/main/java/cn/aprilviolet/highlightbracketpair/adapter/BracketMatchProcessorFactory.java b/src/main/java/cn/aprilviolet/highlightbracketpair/adapter/BracketMatchProcessorFactory.java
new file mode 100644
index 0000000..37ceb37
--- /dev/null
+++ b/src/main/java/cn/aprilviolet/highlightbracketpair/adapter/BracketMatchProcessorFactory.java
@@ -0,0 +1,59 @@
+package cn.aprilviolet.highlightbracketpair.adapter;
+
+import com.intellij.ide.highlighter.XmlFileType;
+import com.intellij.openapi.fileTypes.FileType;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Find different BracketMatchProcessor according to different types
+ *
+ * @author AprilViolet
+ * @version v1.0.0
+ * @date 2021.09.21 14:23
+ * @since v1.0.0
+ */
+public class BracketMatchProcessorFactory {
+ Map braceMatchingMapProcessor = new HashMap<>();
+
+ private BracketMatchProcessorFactory() {
+ braceMatchingMapProcessor.put("Default", new BracketMatchProcessor() {});
+ init();
+ }
+
+ public void addBraceMatching(FileType fileType, BracketMatchProcessor braceMatching) {
+ braceMatchingMapProcessor.put(fileType.getName(), braceMatching);
+ }
+
+ public BracketMatchProcessor getProcessor(FileType fileType) {
+ BracketMatchProcessor braceMatching = braceMatchingMapProcessor.get(fileType.getName());
+ return braceMatching == null ? braceMatchingMapProcessor.get("Default") : braceMatching;
+ }
+
+ private void init() {
+ braceMatchingMapProcessor.put(XmlFileType.INSTANCE.getName(), new XmlBracketMatchProcessor());
+ braceMatchingMapProcessor.put("Vue.js", new XmlBracketMatchProcessor());
+ }
+
+ public static BracketMatchProcessorFactory getInstance() {
+ return BracketMatchProcessorFactory.SingletonInstance.INSTANCE.getInstance();
+ }
+
+ private enum SingletonInstance {
+ /**
+ * Enumeration singleton
+ */
+ INSTANCE;
+
+ private final BracketMatchProcessorFactory bracketMatchProcessorFactory;
+
+ SingletonInstance() {
+ bracketMatchProcessorFactory = new BracketMatchProcessorFactory();
+ }
+
+ BracketMatchProcessorFactory getInstance() {
+ return bracketMatchProcessorFactory;
+ }
+ }
+}
diff --git a/src/main/java/cn/aprilviolet/highlightbracketpair/adapter/BracketMatchProcessorHolder.java b/src/main/java/cn/aprilviolet/highlightbracketpair/adapter/BracketMatchProcessorHolder.java
new file mode 100644
index 0000000..ed31e84
--- /dev/null
+++ b/src/main/java/cn/aprilviolet/highlightbracketpair/adapter/BracketMatchProcessorHolder.java
@@ -0,0 +1,177 @@
+package cn.aprilviolet.highlightbracketpair.adapter;
+
+import com.intellij.openapi.editor.highlighter.HighlighterIterator;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.psi.tree.IElementType;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.Set;
+
+import static cn.aprilviolet.highlightbracketpair.brace.BraceTokenTypes.*;
+
+
+/**
+ * Find difference BracketMatchProcessor
+ *
+ * @author AprilViolet
+ * @version v1.0.0
+ * @date 2021.09.21 15:33
+ * @since v1.0.0
+ */
+public class BracketMatchProcessorHolder {
+ private BracketMatchProcessorHolder() {
+ }
+
+ /**
+ * default return value for no brace offset
+ */
+ public static final int NON_BRACE_OFFSET = -1;
+
+ protected static final Set STRING_TOKEN_SET = new HashSet<>();
+
+ public static final BracketMatchProcessorFactory BRACKET_MATCHING_FACTORY = BracketMatchProcessorFactory.getInstance();
+
+ private static final char L_BRACE_ATTR = '{';
+ private static final char R_BRACE_ATTR = '}';
+
+ private static final char L_BRACKET_ATTR = '[';
+ private static final char R_BRACKET_ATTR = ']';
+
+ private static final char L_PARENTHESIS_ATTR = '(';
+ private static final char R_PARENTHESIS_ATTR = ')';
+
+ private static final char L_CUSP_BRACKETS_ATTR = '<';
+ private static final char R_CUSP_BRACKETS_ATTR = '>';
+
+
+ static {
+ STRING_TOKEN_SET.add(GROOVY_STRING_TOKEN);
+ STRING_TOKEN_SET.add(GROOVY_SINGLE_QUOTE_TOKEN);
+ STRING_TOKEN_SET.add(KOTLIN_STRING_TOKEN);
+ STRING_TOKEN_SET.add(KOTLIN_CHAR_TOKEN);
+ STRING_TOKEN_SET.add(JS_STRING_TOKEN);
+ STRING_TOKEN_SET.add(JAVA_STRING_TOKEN);
+ STRING_TOKEN_SET.add(SCALA_STRING_TOKEN);
+ STRING_TOKEN_SET.add(HASKELL_STRING_TOKEN);
+ }
+
+ /**
+ * Find the left closest brace offset position.
+ *
+ * @param iterator highlighter iterator
+ * @param lparenTokenType left token type to be paired
+ * @param fileText file text
+ * @param fileType file type
+ * @return offset
+ */
+ public static int findLeftBraceOffset(HighlighterIterator iterator, IElementType lparenTokenType, CharSequence fileText,
+ FileType fileType, boolean isBlockCaret, Integer offset) {
+ return BRACKET_MATCHING_FACTORY.getProcessor(fileType)
+ .findLeftParen(iterator, lparenTokenType, fileText, fileType, isBlockCaret, offset);
+ }
+
+ /**
+ * find the right closest brace offset position
+ *
+ * @param iterator highlight iterator
+ * @param rparenTokenType right token type to paired
+ * @param fileText file text
+ * @param fileType file type
+ * @return offset
+ */
+ public static int findRightBraceOffset(HighlighterIterator iterator, IElementType rparenTokenType, CharSequence fileText,
+ FileType fileType, boolean isBlockCaret, Integer offset) {
+
+ return BRACKET_MATCHING_FACTORY.getProcessor(fileType)
+ .findRightParen(iterator, rparenTokenType, fileText, fileType, isBlockCaret, offset);
+ }
+
+ /**
+ * check is the current token type is string token.
+ *
+ * @param tokenType token type
+ * @return is string token
+ */
+ public static boolean isStringToken(IElementType tokenType) {
+ String elementName = tokenType.toString();
+ return STRING_TOKEN_SET.contains(elementName);
+ }
+
+ /**
+ * Find left string symbol matches
+ *
+ * @param fileText Character text
+ * @param offset offset
+ * @return offset
+ */
+ public static int findLeftParen(CharSequence fileText, int offset) {
+ if (offset > fileText.length() || offset < 0) {
+ return NON_BRACE_OFFSET;
+ }
+ Deque indexDeque = new ArrayDeque<>();
+ for (int i = offset - 1; i > -1; i--) {
+ char character = fileText.charAt(i);
+ if (isLeftBrace(character)) {
+ if (!indexDeque.isEmpty()) {
+ indexDeque.removeFirst();
+ continue;
+ }
+ return i;
+ } else if (isRightBrace(character)) {
+ indexDeque.addFirst(i);
+ }
+ }
+ return NON_BRACE_OFFSET;
+ }
+
+ /**
+ * Find right string symbol matches
+ *
+ * @param fileText Character text
+ * @param offset offset
+ * @return offset
+ */
+ public static int findRightParen(CharSequence fileText, int offset) {
+ if (offset > fileText.length() || offset < 0) {
+ return NON_BRACE_OFFSET;
+ }
+ Deque index = new ArrayDeque<>();
+ for (int i = offset; i < fileText.length(); i++) {
+ char character = fileText.charAt(i);
+ if (isRightBrace(character)) {
+ if (!index.isEmpty()) {
+ index.removeFirst();
+ continue;
+ }
+ return i;
+ } else if (isLeftBrace(character)) {
+ index.addFirst(i);
+ }
+ }
+ return NON_BRACE_OFFSET;
+ }
+
+ /**
+ * Determine whether it is left bracket character
+ *
+ * @param character character
+ * @return true:is left character false:otherwise
+ */
+ private static boolean isLeftBrace(char character) {
+ return character == L_BRACE_ATTR || character == L_BRACKET_ATTR
+ || character == L_CUSP_BRACKETS_ATTR || character == L_PARENTHESIS_ATTR;
+ }
+
+ /**
+ * Determine whether it is right bracket character
+ *
+ * @param character character
+ * @return true:is right character false:otherwise
+ */
+ private static boolean isRightBrace(char character) {
+ return character == R_BRACE_ATTR || character == R_BRACKET_ATTR
+ || character == R_CUSP_BRACKETS_ATTR || character == R_PARENTHESIS_ATTR;
+ }
+}
diff --git a/src/main/java/cn/aprilviolet/highlightbracketpair/adapter/XmlBracketMatchProcessor.java b/src/main/java/cn/aprilviolet/highlightbracketpair/adapter/XmlBracketMatchProcessor.java
new file mode 100644
index 0000000..b5ac491
--- /dev/null
+++ b/src/main/java/cn/aprilviolet/highlightbracketpair/adapter/XmlBracketMatchProcessor.java
@@ -0,0 +1,120 @@
+package cn.aprilviolet.highlightbracketpair.adapter;
+
+import cn.aprilviolet.highlightbracketpair.brace.BraceTokenTypes;
+import com.intellij.openapi.editor.highlighter.HighlighterIterator;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlTokenType;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+
+import static com.intellij.codeInsight.highlighting.BraceMatchingUtil.*;
+
+/**
+ * xml bracket enhanced adaptation
+ *
+ * @author AprilViolet
+ * @version v1.0.0
+ * @date 2021.09.21 14:34
+ * @since v1.0.0
+ */
+public class XmlBracketMatchProcessor implements BracketMatchProcessor {
+ /**
+ * Find the left closest brace offset position.
+ *
+ * @param iterator highlighter iterator
+ * @param lparenTokenType left token type to be paired
+ * @param fileText file text
+ * @param fileType file type
+ * @param isBlockCaret is it a block caret
+ * @param offset offset
+ * @return offset
+ */
+ @Override
+ public int findLeftParen(HighlighterIterator iterator, IElementType lparenTokenType, CharSequence fileText,
+ FileType fileType, boolean isBlockCaret, Integer offset) {
+ int initOffset = iterator.atEnd() ? -1 : iterator.getStart();
+ Deque braceStack = new ArrayDeque<>();
+ if (iterator.getTokenType().equals(XmlTokenType.XML_DATA_CHARACTERS)) {
+ int leftParen = BracketMatchProcessorHolder.findLeftParen(fileText, offset);
+ if (leftParen != NON_BRACE_OFFSET && lparenTokenType == BraceTokenTypes.TEXT_TOKEN) {
+ return leftParen;
+ }
+ return NON_BRACE_OFFSET;
+ }
+ for (; !iterator.atEnd(); iterator.retreat()) {
+ final IElementType tokenType = iterator.getTokenType();
+ if (isLBraceToken(iterator, fileText, fileType)) {
+ if (!isBlockCaret && initOffset == iterator.getStart()) {
+ continue;
+ }
+ if (!braceStack.isEmpty()) {
+ IElementType topToken = braceStack.removeFirst();
+ if (!isPairBraces(tokenType, topToken, fileType)) {
+ break; // unmatched braces
+ }
+ } else {
+ if (tokenType == lparenTokenType) {
+ return iterator.getStart();
+ } else {
+ break;
+ }
+ }
+ } else if (isRBraceToken(iterator, fileText, fileType)) {
+ if (initOffset == iterator.getStart()) {
+ continue;
+ }
+ braceStack.addFirst(iterator.getTokenType());
+ }
+ }
+
+ return NON_BRACE_OFFSET;
+ }
+
+ /**
+ * find the right closest brace offset position
+ *
+ * @param iterator highlight iterator
+ * @param rparenTokenType right token type to paired
+ * @param fileText file text
+ * @param fileType file type
+ * @param isBlockCaret is it a block caret
+ * @param offset offset
+ * @return offset
+ */
+ @Override
+ public int findRightParen(HighlighterIterator iterator, IElementType rparenTokenType, CharSequence fileText,
+ FileType fileType, boolean isBlockCaret, Integer offset) {
+ int initOffset = iterator.atEnd() ? -1 : iterator.getStart();
+ if (iterator.getTokenType().equals(XmlTokenType.XML_DATA_CHARACTERS)) {
+ int rightParen = BracketMatchProcessorHolder.findRightParen(fileText, offset);
+ if (rightParen != NON_BRACE_OFFSET && rparenTokenType == BraceTokenTypes.TEXT_TOKEN) {
+ return rightParen;
+ }
+ return NON_BRACE_OFFSET;
+ }
+ Deque braceStack = new ArrayDeque<>();
+ for (; !iterator.atEnd(); iterator.advance()) {
+ final IElementType tokenType = iterator.getTokenType();
+ if (isRBraceToken(iterator, fileText, fileType)) {
+ if (!braceStack.isEmpty()) {
+ IElementType topToken = braceStack.removeFirst();
+ if (!isPairBraces(tokenType, topToken, fileType)) {
+ break; // unmatched braces
+ }
+ } else {
+ if (tokenType == rparenTokenType) {
+ return iterator.getStart();
+ } else {
+ break;
+ }
+ }
+ } else if (isLBraceToken(iterator, fileText, fileType) && !(isBlockCaret && initOffset == iterator.getStart())) {
+ braceStack.addFirst(iterator.getTokenType());
+ }
+ }
+
+ return NON_BRACE_OFFSET;
+ }
+}
diff --git a/src/main/java/cn/aprilviolet/highlightbracketpair/brace/BraceTokenTypes.java b/src/main/java/cn/aprilviolet/highlightbracketpair/brace/BraceTokenTypes.java
index c883825..afe5de9 100644
--- a/src/main/java/cn/aprilviolet/highlightbracketpair/brace/BraceTokenTypes.java
+++ b/src/main/java/cn/aprilviolet/highlightbracketpair/brace/BraceTokenTypes.java
@@ -15,25 +15,30 @@
* @since V1.0.0
*/
public class BraceTokenTypes {
- private final static Map ELEMENT_TYPE_TEXT = new HashMap<>();
+ private BraceTokenTypes() {
+ }
+
+ private static final Map ELEMENT_TYPE_TEXT = new HashMap<>();
+
+ public static final IElementType DOUBLE_QUOTE = new IElementType("DOUBLE_QUOTE", Language.ANY);
- public final static IElementType DOUBLE_QUOTE = new IElementType("DOUBLE_QUOTE", Language.ANY);
+ public static final String GROOVY_STRING_TOKEN = "Gstring";
- public final static String GROOVY_STRING_TOKEN = "Gstring";
+ public static final String GROOVY_SINGLE_QUOTE_TOKEN = "string";
- public final static String GROOVY_SINGLE_QUOTE_TOKEN = "string";
+ public static final String KOTLIN_STRING_TOKEN = "REGULAR_STRING_PART";
- public final static String KOTLIN_STRING_TOKEN = "REGULAR_STRING_PART";
+ public static final String KOTLIN_CHAR_TOKEN = "CHARACTER_LITERAL";
- public final static String KOTLIN_CHAR_TOKEN = "CHARACTER_LITERAL";
+ public static final String JS_STRING_TOKEN = "STRING";
- public final static String JS_STRING_TOKEN = "STRING";
+ public static final String JAVA_STRING_TOKEN = "STRING_LITERAL";
- public final static String JAVA_STRING_TOKEN = "STRING_LITERAL";
+ public static final String SCALA_STRING_TOKEN = "string content";
- public final static String SCALA_STRING_TOKEN = "string content";
+ public static final String HASKELL_STRING_TOKEN = "HaskellTokenType.STRING_LITERAL";
- public final static String HASKELL_STRING_TOKEN = "HaskellTokenType.STRING_LITERAL";
+ public static final IElementType TEXT_TOKEN = new IElementType("TEXT_TOKEN", Language.ANY);
static {
ELEMENT_TYPE_TEXT.put(DOUBLE_QUOTE, "\"");
diff --git a/src/main/java/cn/aprilviolet/highlightbracketpair/component/HighlightEditorCartListener.java b/src/main/java/cn/aprilviolet/highlightbracketpair/component/HighlightEditorCartListener.java
index 1abf6c3..a4536eb 100644
--- a/src/main/java/cn/aprilviolet/highlightbracketpair/component/HighlightEditorCartListener.java
+++ b/src/main/java/cn/aprilviolet/highlightbracketpair/component/HighlightEditorCartListener.java
@@ -51,8 +51,7 @@ public HighlightEditorCartListener(Editor editor) {
*/
@Override
public void caretPositionChanged(@NotNull CaretEvent event) {
- Editor editor = event.getEditor();
- highlightEditorCurrentPair(editor);
+ highlightEditorCurrentPair(event.getEditor());
}
/**
@@ -78,7 +77,7 @@ public void highlightEditorCurrentPair(Editor editor) {
highlighterList.add(highlighterEntry.getRight());
}
- if (highlightBracketPairSettings.getBracketGutterEnable()) {
+ if (Boolean.TRUE.equals(highlightBracketPairSettings.getBracketGutterEnable())) {
// clear braces in gutter
highlighter.eraseHighlight(gutterHighlighterList);
String gutterBracketSize = highlightBracketPairSettings.getGutterBracketSize();
@@ -125,11 +124,6 @@ public void keyTyped(KeyEvent e) {
this.highlightEditorCartListener.highlightEditorCurrentPair(this.editor);
}
- @Override
- public void keyPressed(KeyEvent e) {
- super.keyPressed(e);
- }
-
@Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() != KeyEvent.VK_ESCAPE) {
diff --git a/src/main/java/cn/aprilviolet/highlightbracketpair/extend/CustomSupportedToken.java b/src/main/java/cn/aprilviolet/highlightbracketpair/extend/CustomSupportedToken.java
new file mode 100644
index 0000000..88dfb69
--- /dev/null
+++ b/src/main/java/cn/aprilviolet/highlightbracketpair/extend/CustomSupportedToken.java
@@ -0,0 +1,23 @@
+package cn.aprilviolet.highlightbracketpair.extend;
+
+import cn.aprilviolet.highlightbracketpair.util.Pair;
+import com.intellij.lang.Language;
+import com.intellij.psi.tree.IElementType;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Customer support bracket
+ *
+ * @author AprilViolet
+ * @version v1.0.0
+ * @date 2021.09.21 16:02
+ * @since v1.0.0
+ */
+public class CustomSupportedToken {
+ Map>> addSupported(Map>> languagePairsMap) {
+ return languagePairsMap;
+ }
+}
diff --git a/src/main/java/cn/aprilviolet/highlightbracketpair/extend/VueSupportedToken.java b/src/main/java/cn/aprilviolet/highlightbracketpair/extend/VueSupportedToken.java
new file mode 100644
index 0000000..da8ff57
--- /dev/null
+++ b/src/main/java/cn/aprilviolet/highlightbracketpair/extend/VueSupportedToken.java
@@ -0,0 +1,65 @@
+package cn.aprilviolet.highlightbracketpair.extend;
+
+import cn.aprilviolet.highlightbracketpair.util.Pair;
+import com.intellij.lang.Language;
+import com.intellij.psi.tree.IElementType;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Customer Vue support Bracket
+ *
+ * @author AprilViolet
+ * @version v1.0.0
+ * @date 2021.09.21 16:03
+ * @since v1.0.0
+ */
+public class VueSupportedToken extends CustomSupportedToken {
+ @Override
+ public Map>> addSupported(Map>> languagePairsMap) {
+ Language vue = Language.findLanguageByID("Vue");
+ if (vue == null) {
+ return languagePairsMap;
+ }
+ List> vueJsPairList = languagePairsMap.get(Language.findLanguageByID("VueJS"));
+ List> xmlPairList = languagePairsMap.get(Language.findLanguageByID("XML"));
+ List> cssPairList = languagePairsMap.get(Language.findLanguageByID("CSS"));
+ List> vuePairList = new ArrayList<>();
+ if (null != vueJsPairList) {
+ vuePairList.addAll(vueJsPairList);
+ }
+ if (null != xmlPairList) {
+ vuePairList.addAll(xmlPairList);
+ }
+ if (null != cssPairList) {
+ vuePairList.addAll(cssPairList);
+ }
+ languagePairsMap.put(vue, vuePairList);
+ return languagePairsMap;
+ }
+
+ public enum Singleton {
+ /**
+ * Enumeration singleton
+ */
+ INSTANCE;
+
+ private final VueSupportedToken vueSupportedToken;
+
+ Singleton() {
+ vueSupportedToken = new VueSupportedToken();
+ }
+
+ public VueSupportedToken getInstance() {
+ return vueSupportedToken;
+ }
+
+ public Map>> addSupported(Map>> languagePairsMap) {
+ return vueSupportedToken.addSupported(languagePairsMap);
+ }
+ }
+}
diff --git a/src/main/java/cn/aprilviolet/highlightbracketpair/extend/XmlSupportedToken.java b/src/main/java/cn/aprilviolet/highlightbracketpair/extend/XmlSupportedToken.java
new file mode 100644
index 0000000..7047753
--- /dev/null
+++ b/src/main/java/cn/aprilviolet/highlightbracketpair/extend/XmlSupportedToken.java
@@ -0,0 +1,135 @@
+package cn.aprilviolet.highlightbracketpair.extend;
+
+import cn.aprilviolet.highlightbracketpair.brace.BraceTokenTypes;
+import cn.aprilviolet.highlightbracketpair.util.Pair;
+import com.intellij.lang.Language;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.highlighter.HighlighterIterator;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlTokenType;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Customer Xml support Bracket
+ *
+ * @author AprilViolet
+ * @version v1.0.0
+ * @date 2021.09.21 16:04
+ * @since v1.0.0
+ */
+public class XmlSupportedToken extends CustomSupportedToken {
+ public static String getLeftPart(int start, HighlighterIterator iterator) {
+ int tagNameEnd = 0;
+ Document document = iterator.getDocument();
+ for (; !iterator.atEnd(); iterator.advance()) {
+ IElementType tokenType = iterator.getTokenType();
+ if (tokenType == XmlTokenType.XML_TAG_NAME && iterator.getEnd() > start) {
+ tagNameEnd = iterator.getEnd();
+ continue;
+ }
+ if (tokenType == XmlTokenType.XML_TAG_END && tagNameEnd != 0) {
+ return document.getText(new TextRange(start,
+ iterator.getEnd()));
+ }
+ tagNameEnd = 0;
+ }
+ return "";
+ }
+
+ public static String getLeftPartOnlyName(int start, HighlighterIterator iterator) {
+ Document document = iterator.getDocument();
+ for (; !iterator.atEnd(); iterator.advance()) {
+ IElementType iteratorTokenType = iterator.getTokenType();
+ if (iteratorTokenType == XmlTokenType.XML_TAG_NAME && iterator.getEnd() > start) {
+ String tagWithName = document.getText(new TextRange(start,
+ iterator.getEnd()));
+ iterator.advance();
+ if (iterator.getTokenType() == XmlTokenType.XML_TAG_END) {
+ return document.getText(new TextRange(start,
+ iterator.getEnd()));
+ }
+ return tagWithName;
+ }
+ }
+ return "";
+ }
+
+ public static String getRightPart(int end, HighlighterIterator iterator, int leftIndex) {
+ Document document = iterator.getDocument();
+ Deque xmlTagEnd = new ArrayDeque<>();
+ for (; !iterator.atEnd(); iterator.retreat()) {
+ IElementType tokenType = iterator.getTokenType();
+ if (iterator.getStart() < leftIndex) {
+ if (!xmlTagEnd.isEmpty()) {
+ return document.getText(new TextRange(xmlTagEnd.removeFirst(), end));
+ }
+ break;
+ }
+ if (tokenType == XmlTokenType.XML_END_TAG_START) {
+ return document.getText(new TextRange(iterator.getStart(),
+ end));
+ }
+ if (tokenType == XmlTokenType.XML_TAG_END) {
+ xmlTagEnd.addFirst(iterator.getStart());
+ }
+ }
+ return "";
+ }
+
+ @Override
+ public Map>> addSupported(Map>> languagePairsMap) {
+ Language xml = Language.findLanguageByID("XML");
+ if (xml == null) {
+ return languagePairsMap;
+ }
+
+ List> pairList = languagePairsMap.get(xml);
+ if (pairList == null) {
+ pairList = new ArrayList<>();
+ pairList.add(new Pair<>(XmlTokenType.XML_START_TAG_START, XmlTokenType.XML_TAG_END));
+ pairList.add(new Pair<>(XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER,
+ XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER));
+ pairList.add(new Pair<>(XmlTokenType.XML_START_TAG_START, XmlTokenType.XML_EMPTY_ELEMENT_END));
+ pairList.add(new Pair<>(BraceTokenTypes.TEXT_TOKEN, BraceTokenTypes.TEXT_TOKEN));
+ languagePairsMap.put(xml, pairList);
+ for (Language subLanguage : xml.getDialects()) {
+ List> pairs = languagePairsMap.get(subLanguage);
+ if (pairs != null) {
+ pairs.addAll(pairList);
+ } else {
+ languagePairsMap.put(subLanguage, pairList);
+ }
+ }
+ }
+ return languagePairsMap;
+ }
+
+ public enum Singleton {
+ /**
+ * Enumeration singleton
+ */
+ INSTANCE;
+
+ private final XmlSupportedToken xmlSupportedToken;
+
+ Singleton() {
+ xmlSupportedToken = new XmlSupportedToken();
+ }
+
+ public XmlSupportedToken getInstance() {
+ return xmlSupportedToken;
+ }
+
+ public Map>> addSupported(Map>> map) {
+ return xmlSupportedToken.addSupported(map);
+ }
+ }
+}
diff --git a/src/main/java/cn/aprilviolet/highlightbracketpair/highlighter/AbstractBracketHighlighter.java b/src/main/java/cn/aprilviolet/highlightbracketpair/highlighter/AbstractBracketHighlighter.java
index 2b5256b..2bed859 100644
--- a/src/main/java/cn/aprilviolet/highlightbracketpair/highlighter/AbstractBracketHighlighter.java
+++ b/src/main/java/cn/aprilviolet/highlightbracketpair/highlighter/AbstractBracketHighlighter.java
@@ -1,8 +1,10 @@
package cn.aprilviolet.highlightbracketpair.highlighter;
-import cn.aprilviolet.highlightbracketpair.adapter.BraceMatchingUtilAdapter;
+import cn.aprilviolet.highlightbracketpair.adapter.BracketMatchProcessorHolder;
import cn.aprilviolet.highlightbracketpair.brace.Brace;
import cn.aprilviolet.highlightbracketpair.brace.BracePair;
+import cn.aprilviolet.highlightbracketpair.brace.BraceTokenTypes;
+import cn.aprilviolet.highlightbracketpair.extend.XmlSupportedToken;
import cn.aprilviolet.highlightbracketpair.setting.HighlightBracketPairSettingsPage;
import cn.aprilviolet.highlightbracketpair.util.Pair;
import com.intellij.openapi.editor.Document;
@@ -19,9 +21,11 @@
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.xml.XmlTokenType;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -38,12 +42,12 @@
* @date 2021.07.31 14:50
* @since V1.0.0
*/
-abstract public class AbstractBracketHighlighter {
- public final static int NON_OFFSET = -1;
+public abstract class AbstractBracketHighlighter {
+ public static final Integer NON_OFFSET = -1;
- public final static int HIGHLIGHT_LAYER_WEIGHT = 100;
+ public static final Integer HIGHLIGHT_LAYER_WEIGHT = 100;
- public final static BracePair EMPTY_BRACE_PAIR = new BracePair.BracePairBuilder()
+ public static final BracePair EMPTY_BRACE_PAIR = new BracePair.BracePairBuilder()
.leftOffset(NON_OFFSET).rightOffset(NON_OFFSET).build();
protected Editor editor;
@@ -66,7 +70,7 @@ abstract public class AbstractBracketHighlighter {
public static final String BRACE_ATTR_GUTTER = "|";
- public AbstractBracketHighlighter(Editor editor) {
+ protected AbstractBracketHighlighter(Editor editor) {
this.editor = editor;
this.project = this.editor.getProject();
this.document = this.editor.getDocument();
@@ -245,18 +249,44 @@ private BracePair findCloseBracePairInBraceTokens(int offset) {
EditorHighlighter editorHighlighter = ((EditorEx) editor).getHighlighter();
boolean isBlockCaret = this.isBlockCaret();
List> braceTokens = this.getSupportedBraceToken();
- for (Pair braceToken : braceTokens) {
+ for (Pair braceTokenPair : braceTokens) {
HighlighterIterator leftTraverseIterator = editorHighlighter.createIterator(offset);
HighlighterIterator rightTraverseIterator = editorHighlighter.createIterator(offset);
- int leftBraceOffset = BraceMatchingUtilAdapter.findLeftBraceOffset(leftTraverseIterator,
- braceToken.getLeft(), this.fileText, this.fileType, isBlockCaret);
- int rightBraceOffset = BraceMatchingUtilAdapter.findRightBraceOffset(rightTraverseIterator,
- braceToken.getRight(), this.fileText, this.fileType, isBlockCaret);
+ int leftBraceOffset = BracketMatchProcessorHolder.findLeftBraceOffset(leftTraverseIterator,
+ braceTokenPair.getLeft(), this.fileText, this.fileType, isBlockCaret, offset);
+ int rightBraceOffset = BracketMatchProcessorHolder.findRightBraceOffset(rightTraverseIterator,
+ braceTokenPair.getRight(), this.fileText, this.fileType, isBlockCaret, offset);
if (leftBraceOffset != NON_OFFSET && rightBraceOffset != NON_OFFSET) {
- return new BracePair.BracePairBuilder().leftType(braceToken.getLeft()).rightType(braceToken.getRight()).
- leftIterator(leftTraverseIterator).rightIterator(rightTraverseIterator).build();
+ if (braceTokenPair.getRight().equals(XmlTokenType.XML_TAG_END)) {
+ HighlighterIterator leftIterator = editorHighlighter.createIterator(leftBraceOffset);
+ HighlighterIterator rightIterator = editorHighlighter.createIterator(rightBraceOffset);
+ String leftText = XmlSupportedToken.getLeftPartOnlyName(leftBraceOffset, leftIterator);
+ String rightText = XmlSupportedToken.getRightPart(rightBraceOffset + 1, rightIterator, leftBraceOffset);
+ return new BracePair.BracePairBuilder().leftType(braceTokenPair.getLeft())
+ .rightType(braceTokenPair.getRight()).leftText(leftText).rightText(rightText)
+ .leftOffset(leftBraceOffset).rightOffset(rightBraceOffset - rightText.length() + 1).build();
+ }
+
+ if (braceTokenPair.getRight().equals(XmlTokenType.XML_EMPTY_ELEMENT_END)) {
+ HighlighterIterator leftIterator = editorHighlighter.createIterator(leftBraceOffset);
+ String leftText = XmlSupportedToken.getLeftPartOnlyName(leftBraceOffset, leftIterator);
+ String rightText = document.getText(new TextRange(rightTraverseIterator.getStart(),
+ rightTraverseIterator.getEnd()));
+ return new BracePair.BracePairBuilder().leftType(braceTokenPair.getLeft())
+ .rightType(braceTokenPair.getRight()).leftText(leftText).rightText(rightText)
+ .leftOffset(leftBraceOffset).rightOffset(rightTraverseIterator.getStart()).build();
+ }
+ if (braceTokenPair.getRight().equals(BraceTokenTypes.TEXT_TOKEN)) {
+ String leftText = document.getText(new TextRange(leftBraceOffset, leftBraceOffset + 1));
+ String rightText = document.getText(new TextRange(rightBraceOffset, rightBraceOffset + 1));
+ return new BracePair.BracePairBuilder().leftType(braceTokenPair.getLeft())
+ .rightType(braceTokenPair.getRight()).leftText(leftText).rightText(rightText)
+ .leftOffset(leftBraceOffset).rightOffset(rightBraceOffset).build();
+ }
+ return new BracePair.BracePairBuilder().leftType(braceTokenPair.getLeft()).rightType(braceTokenPair.getRight())
+ .leftIterator(leftTraverseIterator).rightIterator(rightTraverseIterator).build();
}
}
return EMPTY_BRACE_PAIR;
@@ -277,7 +307,7 @@ private BracePair findCloseBracePairInStringSymbols(int offset) {
HighlighterIterator iterator = editorHighlighter.createIterator(offset);
IElementType type = iterator.getTokenType();
boolean isBlockCaret = this.isBlockCaret();
- if (!BraceMatchingUtilAdapter.isStringToken(type)) {
+ if (!BracketMatchProcessorHolder.isStringToken(type)) {
return EMPTY_BRACE_PAIR;
}
diff --git a/src/main/java/cn/aprilviolet/highlightbracketpair/highlighter/DefaultAbstractBracketHighlighter.java b/src/main/java/cn/aprilviolet/highlightbracketpair/highlighter/DefaultAbstractBracketHighlighter.java
index cede9d5..2d392c5 100644
--- a/src/main/java/cn/aprilviolet/highlightbracketpair/highlighter/DefaultAbstractBracketHighlighter.java
+++ b/src/main/java/cn/aprilviolet/highlightbracketpair/highlighter/DefaultAbstractBracketHighlighter.java
@@ -1,5 +1,7 @@
package cn.aprilviolet.highlightbracketpair.highlighter;
+import cn.aprilviolet.highlightbracketpair.extend.VueSupportedToken;
+import cn.aprilviolet.highlightbracketpair.extend.XmlSupportedToken;
import cn.aprilviolet.highlightbracketpair.util.Pair;
import com.intellij.lang.BracePair;
import com.intellij.lang.Language;
@@ -8,7 +10,12 @@
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.tree.IElementType;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
/**
* Default Brace Highlighter to highlight all supported brace pair.
@@ -22,26 +29,13 @@ public class DefaultAbstractBracketHighlighter extends AbstractBracketHighlighte
/**
* Default registered languages brace
*/
- public static Map>> LANGUAGE_BRACE_PAIRS = new HashMap<>();
+ protected static final Map>> LANGUAGE_BRACE_PAIRS = new HashMap<>();
/*
* Get all the registered languages brace pairs and cache it.
*/
static {
- Collection languageList = Language.getRegisteredLanguages();
- for (Language language : languageList) {
- PairedBraceMatcher pairedBraceMatcher = LanguageBraceMatching.INSTANCE.forLanguage(language);
- if (pairedBraceMatcher != null) {
- BracePair[] bracePairs = pairedBraceMatcher.getPairs();
- List> braceList = new LinkedList<>();
- for (BracePair bracePair : bracePairs) {
- Pair braceEntry =
- new Pair<>(bracePair.getLeftBraceType(), bracePair.getRightBraceType());
- braceList.add(braceEntry);
- }
- LANGUAGE_BRACE_PAIRS.put(language, braceList);
- }
- }
+ refresh();
}
/**
@@ -62,6 +56,40 @@ public DefaultAbstractBracketHighlighter(Editor editor) {
public List> getSupportedBraceToken() {
Language language = this.psiFile.getLanguage();
List> braceList = LANGUAGE_BRACE_PAIRS.get(language);
- return braceList == null ? new LinkedList<>() : braceList;
+ return braceList == null ? customSupportedBraceToken(language) : braceList;
+ }
+
+ /**
+ * Query Pair from custom BraceToken
+ *
+ * @param language language type
+ * @return Pair
+ */
+ private List> customSupportedBraceToken(Language language) {
+ refresh();
+ XmlSupportedToken.Singleton.INSTANCE.addSupported(LANGUAGE_BRACE_PAIRS);
+ VueSupportedToken.Singleton.INSTANCE.addSupported(LANGUAGE_BRACE_PAIRS);
+ List> braceList = LANGUAGE_BRACE_PAIRS.get(language);
+ return braceList == null ? new ArrayList<>() : braceList;
+ }
+
+ /**
+ * Initialize the registered language Pair
+ */
+ private static void refresh () {
+ Collection languageList = Language.getRegisteredLanguages();
+ for (Language language : languageList) {
+ PairedBraceMatcher pairedBraceMatcher = LanguageBraceMatching.INSTANCE.forLanguage(language);
+ if (pairedBraceMatcher != null) {
+ BracePair[] bracePairs = pairedBraceMatcher.getPairs();
+ List> braceList = new LinkedList<>();
+ for (BracePair bracePair : bracePairs) {
+ Pair braceEntry =
+ new Pair<>(bracePair.getLeftBraceType(), bracePair.getRightBraceType());
+ braceList.add(braceEntry);
+ }
+ LANGUAGE_BRACE_PAIRS.put(language, braceList);
+ }
+ }
}
}
diff --git a/src/main/java/cn/aprilviolet/highlightbracketpair/setting/HighlightBracketPairSettingComponent.java b/src/main/java/cn/aprilviolet/highlightbracketpair/setting/HighlightBracketPairSettingComponent.java
index 2506d28..479e053 100644
--- a/src/main/java/cn/aprilviolet/highlightbracketpair/setting/HighlightBracketPairSettingComponent.java
+++ b/src/main/java/cn/aprilviolet/highlightbracketpair/setting/HighlightBracketPairSettingComponent.java
@@ -23,7 +23,7 @@ public class HighlightBracketPairSettingComponent {
/**
* setting main panel
*/
- private final JPanel bracketMainPanel;
+ private final JBPanel bracketMainPanel;
/**
* Open render bracket in gutter
diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml
index 8971a78..dc26b1b 100644
--- a/src/main/resources/META-INF/plugin.xml
+++ b/src/main/resources/META-INF/plugin.xml
@@ -1,7 +1,7 @@
HighlightBracketPair
HighlightBracketPair
- 1.1.0
+ 1.3.0
AprilViolet
1.3.0
+
+ -
+ Feature:Extension enhancement for Xml
+
+
1.2.0
-
- Feature:customize the color and size of gutter brackets.
+ Feature:customize the color and size of gutter brackets.
1.1.0
-
- Feature:render bracket in gutter.
+ Feature:render bracket in gutter.
+
+ -
Fixed:Fix that the listener renders multiple times