diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..6bb66b660 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,45 @@ +# based on https://github.com/alexkaratarakis/gitattributes/ + +# Handle line endings automatically for files detected as text +# and leave all files detected as binary untouched. +* text=auto + +# +# The above will handle all files NOT found below +# +# These files are text and should be normalized (Convert crlf => lf) +*.gitattributes text +.gitignore text +*.bash text eol=lf +*.bat text eol=crlf +*.cmd text eol=crlf +*.css text diff=css +*.exsd text +*.htm text diff=html +*.html text diff=html +*.ini text +*.md text diff=markdown +*.java text diff=java +*.js text +*.json text +*.properties text +*.sh text +*.tmLanguage text +*.ts text +*.txt text +*.xsd text +*.xml text +*.yaml text +*.yml text +MANIFEST.MF text +Dockerfile text eol=lf +Jenkinsfile text +LICENSE text + +# These files are binary and should be left untouched +# (binary is a macro for -text -diff) +*.gif binary +*.ico binary +*.jpeg binary +*.jpg binary +*.png binary diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f71fb86bf..a795f29a6 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,7 +1,20 @@ +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates version: 2 updates: +- package-ecosystem: github-actions + directory: / + schedule: + interval: daily + commit-message: + prefix: fix + prefix-development: chore + include: scope - package-ecosystem: maven directory: "/" schedule: interval: daily - open-pull-requests-limit: 10 \ No newline at end of file + commit-message: + prefix: fix + prefix-development: chore + include: scope + open-pull-requests-limit: 10 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..34022d8b3 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,87 @@ +# https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions +name: Build + +on: + push: + branches: # build all branches + - '**' + tags-ignore: # but don't build tags + - '**' + paths-ignore: + - '**/*.md' + - '.github/*.yml' + pull_request: + workflow_dispatch: + # https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/ + inputs: + additional_maven_args: + description: 'Additional Maven Args' + required: false + default: '' + +defaults: + run: + shell: bash + +jobs: + + build: + runs-on: ubuntu-latest + steps: + - name: Git Checkout + uses: actions/checkout@v3 #https://github.com/actions/checkout + + - name: Set up JDK 11 + uses: actions/setup-java@v3 # https://github.com/actions/setup-java + with: + distribution: 'zulu' + java-version: 11 + + - name: Install xvfb + run: sudo apt-get install -o Acquire::Retries=3 --no-install-recommends -y xvfb + + - name: "Cache: Local Maven Repository" + uses: actions/cache@v3 + with: + path: | + ~/.m2/repository + !~/.m2/**/*SNAPSHOT* + key: ${{ runner.os }}-mvnrepo-${{ hashFiles('**/pom.xml') }}-${{ hashFiles('**/target-platform/tm4e-target.target') }} + restore-keys: | + ${{ runner.os }}-mvnrepo- + + - name: Set up Maven + uses: stCarolas/setup-maven@v4.3 + with: + maven-version: 3.8.5 + + + - name: Build with Maven + id: maven-build + run: | + set -eu + + MAVEN_OPTS="${MAVEN_OPTS:-}" + MAVEN_OPTS="$MAVEN_OPTS -XX:+TieredCompilation -XX:TieredStopAtLevel=1" # https://zeroturnaround.com/rebellabs/your-maven-build-is-slow-speed-it-up/ + MAVEN_OPTS="$MAVEN_OPTS -Djava.security.egd=file:/dev/./urandom" # https://stackoverflow.com/questions/58991966/what-java-security-egd-option-is-for/59097932#59097932 + MAVEN_OPTS="$MAVEN_OPTS -Dorg.slf4j.simpleLogger.showDateTime=true -Dorg.slf4j.simpleLogger.dateTimeFormat=HH:mm:ss,SSS" # https://stackoverflow.com/questions/5120470/how-to-time-the-different-stages-of-maven-execution/49494561#49494561 + MAVEN_OPTS="$MAVEN_OPTS -Xmx1024m -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Dhttps.protocols=TLSv1.2" + echo " -> MAVEN_OPTS: $MAVEN_OPTS" + export MAVEN_OPTS + + # prevent "org.eclipse.swt.SWTError: No more handles [gtk_init_check() failed]" + xvfb-run mvn \ + --errors \ + --update-snapshots \ + --batch-mode \ + --show-version \ + --no-transfer-progress \ + ${{ github.event.inputs.additional_maven_args }} \ + clean verify + + - name: "Delete intermediate build artifacts" + uses: geekyeggo/delete-artifact@1-glob-support # https://github.com/GeekyEggo/delete-artifact/ + with: + name: "*" + useGlob: true + failOnError: false diff --git a/.github/workflows/licensecheck.yml b/.github/workflows/licensecheck.yml new file mode 100644 index 000000000..bfde8fa5f --- /dev/null +++ b/.github/workflows/licensecheck.yml @@ -0,0 +1,35 @@ +# This workflow will build a Java project with Maven +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + +name: License check + +on: + push: + branches: + - '*' + pull_request: + branches: + - '*' + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 11 + uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'adopt' + - name: Cache local Maven repository + uses: actions/cache@v3 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + - name: License check + run: | + mvn -U -V -e -B -ntp org.eclipse.dash:license-tool-plugin:license-check --file pom.xml -Ddash.fail=true diff --git a/.gitignore b/.gitignore index 3d081ef4e..6a06219e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,21 @@ -.settings +# Eclipse /bin -/.project -target \ No newline at end of file +/*/bin +**/.settings/* +!**/.settings/org.eclipse.core.resoures.prefs +!**/.settings/org.eclipse.jdt.core.prefs +!**/.settings/org.eclipse.pde.core.prefs + +# Eclipse GFM Viewer +*.md.html + +# Maven +/target +/*/target + +# OSX +.DS_Store + +# Vim +*.swo +*.swp diff --git a/.project b/.project new file mode 100644 index 000000000..1548310c4 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + tm4e + + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + + diff --git a/Jenkinsfile b/Jenkinsfile index 7992cda8b..91891ef14 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -10,12 +10,25 @@ pipeline { buildDiscarder(logRotator(numToKeepStr:'10')) } stages { + stage('initialize PGP') { + steps { + withCredentials([file(credentialsId: 'secret-subkeys.asc', variable: 'KEYRING')]) { + sh 'gpg --batch --import "${KEYRING}"' + sh 'for fpr in $(gpg --list-keys --with-colons | awk -F: \'/fpr:/ {print $10}\' | sort -u); do echo -e "5\ny\n" | gpg --batch --command-fd 0 --expert --edit-key ${fpr} trust; done' + } + } + } stage('Build') { steps { withMaven(maven:'apache-maven-latest', mavenLocalRepo: '$WORKSPACE/.m2') { - wrap([$class: 'Xvnc', useXauthority: true]) { - sh 'mvn clean verify -Dmaven.test.error.ignore=true -Dmaven.test.failure.ignore=true -PpackAndSign' - } + withCredentials([string(credentialsId: 'gpg-passphrase', variable: 'KEYRING_PASSPHRASE')]) { + wrap([$class: 'Xvnc', useXauthority: true]) { + sh 'mvn clean verify \ + -Dmaven.test.error.ignore=true -Dmaven.test.failure.ignore=true \ + -Psign -Dgpg.passphrase="${KEYRING_PASSPHRASE}"' + + } + } } } post { diff --git a/README.md b/README.md index d0b6e7172..aa76a23b2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ # Eclipse tm4e - TextMate and language-configuration support for Java and in Eclipse IDE -TM4E brings Java API to tokenize textual documents according to TextMate grammars with an Eclipse IDE client that can do syntax highlighting according to this tokenization; and Eclipse IDE client for VSCode [Language Configuration](https://code.visualstudio.com/docs/extensionAPI/extension-points#_contributeslanguages) to support matching bracket, auto close, on enter support. +[![Build Status](https://github.com/eclipse/tm4e/actions/workflows/build.yml/badge.svg)](https://github.com/eclipse/tm4e/actions/workflows/build.yml) +[![License](https://img.shields.io/github/license/eclipse/tm4e.svg?color=blue)](LICENSE) + +TM4E brings Java API to tokenize textual documents according to TextMate grammars with an Eclipse IDE client that can do syntax highlighting according to this tokenization; and Eclipse IDE client for VSCode [Language Configuration](https://code.visualstudio.com/api/references/contribution-points#contributes.languages) to support matching bracket, auto close, on enter support. `tm4e` is an [official Eclipse.org project](https://projects.eclipse.org/projects/technology.tm4e) so it conforms to typical Eclipse.org requirements and guarantees. @@ -8,7 +11,7 @@ TM4E brings Java API to tokenize textual documents according to TextMate grammar ### in Eclipse IDE or RCP applications -You can install `tm4e` with the update site [http://download.eclipse.org/tm4e/snapshots/](http://download.eclipse.org/tm4e/snapshots/). TM4E is usually installed together with its consumers, so end-user should usually not need to directly install it. +You can install `tm4e` with the update site [https://download.eclipse.org/tm4e/snapshots/](https://download.eclipse.org/tm4e/snapshots/). TM4E is usually installed together with its consumers, so end-user should usually not need to directly install it. ### as a Java API with Maven @@ -24,35 +27,36 @@ The following class and modules should be used as entry point provides: * [org.eclipse.tm4e.ui](https://github.com/eclipse/tm4e/tree/master/org.eclipse.tm4e.ui) provides the Eclipse **org.eclipse.jface.text.presentation.IPresentationReconciler** [TMPresentationReconciler](https://github.com/eclipse/tm4e/blob/master/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/text/TMPresentationReconciler.java) which is able to tokenize an editor content by using a given JSON, PList TextMate grammar and do syntax coloration. See [UI](https://github.com/eclipse/tm4e/wiki/UI) section for more information. - * [org.eclipse.tm4e.languageconfiguration](https://github.com/eclipse/tm4e/tree/master/org.eclipse.tm4e.languageconfiguration) provides the VSCode [Language Configuration](https://code.visualstudio.com/docs/extensionAPI/extension-points#_contributeslanguages) to support matching bracket, auto close, on enter support with a simple **language-configuration.json**. - + * [org.eclipse.tm4e.languageconfiguration](https://github.com/eclipse/tm4e/tree/master/org.eclipse.tm4e.languageconfiguration) provides the VSCode [Language Configuration](https://code.visualstudio.com/api/references/contribution-points#contributes.languages) to support matching bracket, auto close, on enter support with a simple **language-configuration.json**. + Here a sample with TypeScript: -![TypeScript Editor](https://github.com/eclipse/tm4e/wiki/images/TypeScriptEditor.png) +![TypeScript Editor](https://raw.githubusercontent.com/eclipse/wildwebdeveloper/master/documentation-files/typescript38.png) ## 👪 Who is using tm4e? Here are some projects that use tm4e: * Eclipse IDE languages and frameworks integrations - * [Eclipse Corrosion](https://github.com/eclipse/corrosion) Rust development tools in Eclipse IDE. - * [Eclipse aCute](https://github.com/eclipse/aCute) C# edition in Eclipse IDE. - * [Eclipse Wild Web Developer](https://github.com/eclipse/wildwebdeveloper) a simple and productive Web Development Tools in the Eclipse IDE. - * [Eclipse ShellWax](https://github.com/eclipse/shellwax) is a rich Bash script editor in the Eclipse IDE. - * [LiClipseText](http://www.liclipse.com/text/) enables Eclipse to be used as a general-purpose text editor, providing support for several languages out of the box. - * [typescript.java](https://github.com/angelozerr/typescript.java) (Deprecated) TypeScript IDE for Eclipse with JSDT & tsserver. - * [EditorConfig for Eclipse](https://github.com/angelozerr/ec4e) EditorConfig for Eclipse with GenericEditor. - * [Phaser Editor 2D](https://phasereditor2d.com) An IDE for the creation of HTML5 games. - * [Solargraph](https://github.com/PyvesB/eclipse-solargraph) Ruby edition in Eclipse IDE. - * [Dartboard](https://github.com/eclipse/dartboard) Dart language support in the Eclipse IDE. -* [Apache NetBeans](https://github.com/apache/netbeans) is a multi-language IDE written in Java and uses TM4E core parts to support syntax highlighting based on TextMate grammars - + * [Eclipse Corrosion](https://github.com/eclipse/corrosion) - Rust development tools in Eclipse IDE. + * [Eclipse aCute](https://github.com/eclipse/aCute) - C# edition in Eclipse IDE. + * [Eclipse Wild Web Developer](https://github.com/eclipse/wildwebdeveloper) - Simple and productive Web Development Tools in the Eclipse IDE. + * [Eclipse ShellWax](https://github.com/eclipse/shellwax) - A shell script development plugin for the Eclipse IDE, providing a rich edition experience through integration with the [Bash Language Server](https://github.com/bash-lsp/bash-language-server). + * [LiClipseText](https://www.liclipse.com/text/) - An editor which enables Eclipse to be used as a general-purpose text editor, providing support for multiple languages out of the box. + * [typescript.java](https://github.com/angelozerr/typescript.java) *(Deprecated)* - TypeScript IDE for Eclipse with JSDT & tsserver. + * [EditorConfig for Eclipse](https://github.com/angelozerr/ec4e) - EditorConfig for Eclipse with GenericEditor. + * [Phaser Editor 2D](https://phasereditor2d.com) - An IDE for the creation of HTML5 games. + * [Solargraph](https://github.com/PyvesB/eclipse-solargraph) - Ruby development tools for Eclipse. + * [Dartboard](https://github.com/eclipse/dartboard) - Dart language support in the Eclipse IDE. + * [haxe4e](https://github.com/haxe4e/haxe4e) - [Haxe](https://haxe.org/) programming language support for the Eclipse IDE. +* [Apache NetBeans](https://github.com/apache/netbeans) - A multi-language IDE written in Java that uses TM4E core parts to support syntax highlighting based on TextMate grammars. + ## 👷 Get support and contribute -* **License and community**: `tm4e` is a community open-source project licensed under the Eclipse Public License 1.0. -* **Support:** You can ask (and answer!) questions, report bugs, and request features using [GitHub issues](http://github.com/eclipse/tm4e/issues). +* **License and community**: `tm4e` is a community open-source project licensed under the [Eclipse Public License 2.0](LICENSE). +* **Support**: You can ask (and answer!) questions, report bugs, and request features using [GitHub issues](https://github.com/eclipse/tm4e/issues). * **Git**: This `eclipse/tm4e` repository is the reference repository to contribute to `tm4e` -* **Build**: build can be performed with a simple `mvn clean verify`, continuous integration and deployment is performed by CI jobs at https://hudson.eclipse.org/tm4e -* **Continuous testing, integration and deployment** is performed by CI jobs at https://hudson.eclipse.org/tm4e +* **Build**: build can be performed with a simple `mvn clean verify`, continuous integration and deployment is performed by CI jobs at https://ci.eclipse.org/tm4e/ +* **Continuous testing, integration and deployment** is performed by CI jobs at https://ci.eclipse.org/tm4e/ and https://github.com/eclipse/tm4e/actions * **Developers mailing-list**: Contributors are also expected to subscribe the [tm4e-dev mailing-list](https://dev.eclipse.org/mailman/listinfo/tm4e-dev). * **Becoming a committer**: as usual with Eclipse.org projects, anyone who's made significant contributions and who's upheld quality standards alongside good judgement and open-mindedness. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index cfb94193e..a47433fda 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -4,13 +4,45 @@ This page describes the noteworthy improvements provided by each release of Ecli ### Next release... -## 0.4.3 +## 0.4.5 * 📅 Release Date (tentative): ? -* All changes: https://github.com/eclipse/tm4e/compare/0.4.2...0.4.3 +* All changes: https://github.com/eclipse/tm4e/compare/0.4.4...master ### Latest release +## 0.4.4 + +* 📅 Release Date: May 11th 2022 +* All changes: https://github.com/eclipse/tm4e/compare/0.4.3...0.4.4 + + +* Many many many... code improvements +* Dependency updates +* Bugfixes in file detection and compare editor + +## 0.4.3 + +* 📅 Release Date: 19th November 2021 +* All changes: https://github.com/eclipse/tm4e/compare/0.4.2...0.4.3 + +#### Support locations outside a local file system + +This allows to have syntax highlighting for buffers that are not backed by a filesystem locations. + +#### Compatible with viewers that are not IProjectionViewer + +Avoid an exception making TM4E incompatible with most simple ITextViewer in some case. + +#### Fix content-type detection + +Parent content-type are taken into account and allow to enable syntax highlighting for the children of content-types which are bound to a grammar/scope as well, without extra configuration. + +#### Choose default theme according to background color of the widget + +By default, TM4E now decides of the best theme to use according to the background color of the text widget. This allows to get a better text theme when mixing dark global them with light background or editor, or light global theme with dark background in editor. + + ## 0.4.2 * 📅 Release Date (tentative): 6th September 2021 diff --git a/org.eclipse.tm4e.core.tests/.classpath b/org.eclipse.tm4e.core.tests/.classpath index d3fc9157f..71f21812a 100644 --- a/org.eclipse.tm4e.core.tests/.classpath +++ b/org.eclipse.tm4e.core.tests/.classpath @@ -6,14 +6,21 @@ - + - + + + + + + + + - + - + diff --git a/org.eclipse.tm4e.core.tests/.gitignore b/org.eclipse.tm4e.core.tests/.gitignore deleted file mode 100644 index 934e0e06f..000000000 --- a/org.eclipse.tm4e.core.tests/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/bin -/target diff --git a/org.eclipse.tm4e.core.tests/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.tm4e.core.tests/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..f648802b5 --- /dev/null +++ b/org.eclipse.tm4e.core.tests/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,518 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.APILeak=warning +org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning +org.eclipse.jdt.core.compiler.problem.fallthroughCase=info +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=info +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=enabled +org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=11 +org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false +org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false +org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter=0 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type=49 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assertion_message=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0 +org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_record_components=16 +org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_type_annotations=0 +org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0 +org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch=0 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_constructor=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false +org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true +org.eclipse.jdt.core.formatter.comment.format_block_comments=false +org.eclipse.jdt.core.formatter.comment.format_header=true +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.indent_tag_description=false +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=120 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_not_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false +org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.text_block_indentation=0 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false +org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true +org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true +org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true +org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true +org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/org.eclipse.tm4e.core.tests/pom.xml b/org.eclipse.tm4e.core.tests/pom.xml index 3af55b267..d2ad9fb95 100644 --- a/org.eclipse.tm4e.core.tests/pom.xml +++ b/org.eclipse.tm4e.core.tests/pom.xml @@ -1,11 +1,29 @@ - - 4.0.0 - org.eclipse.tm4e.core.tests - eclipse-test-plugin - 0.4.1-SNAPSHOT - - org.eclipse - org.eclipse.tm4e - 0.3.2-SNAPSHOT - + + 4.0.0 + org.eclipse.tm4e.core.tests + eclipse-test-plugin + 0.4.1-SNAPSHOT + + org.eclipse + org.eclipse.tm4e + 0.3.2-SNAPSHOT + + + + + + + org.eclipse.tycho + tycho-compiler-plugin + + + + test-cases/**/*.java + + + + + + diff --git a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/GrammarSuiteTest.java b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/GrammarSuiteTest.java index 34205c120..29ec11aa7 100644 --- a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/GrammarSuiteTest.java +++ b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/GrammarSuiteTest.java @@ -1,92 +1,94 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.grammar; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.eclipse.tm4e.core.grammar.internal.MatcherTestImpl; -import org.eclipse.tm4e.core.grammar.internal.RawTestImpl; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.DynamicTest; -import org.junit.jupiter.api.TestFactory; - -import com.google.gson.GsonBuilder; -import com.google.gson.JsonIOException; -import com.google.gson.JsonSyntaxException; -import com.google.gson.reflect.TypeToken; - -/** - * VSCode TextMate grammar tests which uses same vscode-textmate tests located - * at src\test\resources\test-cases - * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/tests/tests.ts - * - */ -public class GrammarSuiteTest { - - private static final File REPO_ROOT = new File("src/test/resources"); - - // TODO: fix thoses tests: - // It seems that problem comes from with encoding. OnigString should support UTF-16 like https://github.com/atom/node-oniguruma/blob/master/src/onig-string.cc - private static final List IGNORE_TESTS = List.of("TEST #24", "TEST #66"); - - @TestFactory @DisplayName("Tokenization /first-mate/") - Collection firstMate() throws Exception { - return createVSCodeTestSuite(new File(REPO_ROOT, "test-cases/first-mate/tests.json")); - } - - @TestFactory @DisplayName("Tokenization /suite1/ tests.json") - Collection testsJSon() throws Exception { - return createVSCodeTestSuite(new File(REPO_ROOT, "test-cases/suite1/tests.json")); - } - - @TestFactory @DisplayName("Tokenization /suite1/ whileTests.json") - Collection whileTests() throws Exception { - return createVSCodeTestSuite(new File(REPO_ROOT, "test-cases/suite1/whileTests.json")); - } - - - private List createVSCodeTestSuite(File testLocation) throws Exception { - Type listType = new TypeToken>() { - }.getType(); - List tests = new GsonBuilder().create().fromJson(new FileReader(testLocation), listType); - List dynamicTests = new ArrayList<>(); - for (RawTestImpl test : tests) { - if (!IGNORE_TESTS.contains(test.getDesc())) { - test.setTestLocation(testLocation); - dynamicTests.add(DynamicTest.dynamicTest(test.getDesc(), () -> test.executeTest())); - } - } - return dynamicTests; - } - - @TestFactory @DisplayName("Matcher tests") - Collection dynamicTestsWithCollection() throws JsonIOException, JsonSyntaxException, FileNotFoundException { - Type listType = new TypeToken>() { - }.getType(); - List tests = new GsonBuilder().create() - .fromJson(new FileReader(new File(REPO_ROOT, "matcher-tests.json")), listType); - List dynamicTests = new ArrayList<>(); - int i = 0; - for (MatcherTestImpl test : tests) { - dynamicTests.add(DynamicTest.dynamicTest("Test #" + (i++), () -> test.executeTest())); - } - return dynamicTests; - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.grammar; + +import java.io.File; +import java.io.FileReader; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.tm4e.core.grammar.internal.MatcherTestImpl; +import org.eclipse.tm4e.core.grammar.internal.RawTestImpl; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.TestFactory; + +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; + +/** + * VSCode TextMate grammar tests which uses same vscode-textmate tests located at src\test\resources\test-cases + * + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/tests/tests.ts + */ +public class GrammarSuiteTest { + + private static final File REPO_ROOT = new File("src/main/resources"); + + // TODO: fix thoses tests: + // It seems that problem comes from with encoding. OnigString should support UTF-16 like + // https://github.com/atom/node-oniguruma/blob/master/src/onig-string.cc + private static final List IGNORE_TESTS = List.of("TEST #24", "TEST #66"); + + @TestFactory + @DisplayName("Tokenization /first-mate/") + Collection firstMate() throws Exception { + return createVSCodeTestSuite(new File(REPO_ROOT, "test-cases/first-mate/tests.json")); + } + + @TestFactory + @DisplayName("Tokenization /suite1/ tests.json") + Collection testsJSon() throws Exception { + return createVSCodeTestSuite(new File(REPO_ROOT, "test-cases/suite1/tests.json")); + } + + @TestFactory + @DisplayName("Tokenization /suite1/ whileTests.json") + Collection whileTests() throws Exception { + return createVSCodeTestSuite(new File(REPO_ROOT, "test-cases/suite1/whileTests.json")); + } + + private List createVSCodeTestSuite(final File testLocation) throws Exception { + try (var fileReader = new FileReader(testLocation)) { + final Type listType = new TypeToken>() { + }.getType(); + final List tests = new GsonBuilder().create().fromJson(fileReader, listType); + final var dynamicTests = new ArrayList(); + for (final RawTestImpl test : tests) { + if (!IGNORE_TESTS.contains(test.getDesc())) { + test.setTestLocation(testLocation); + dynamicTests.add(DynamicTest.dynamicTest(test.getDesc(), test::executeTest)); + } + } + return dynamicTests; + } + } + + @TestFactory + @DisplayName("Matcher tests") + Collection dynamicTestsWithCollection() throws Exception { + try (var fileReader = new FileReader(new File(REPO_ROOT, "matcher-tests.json"))) { + final Type listType = new TypeToken>() { + }.getType(); + final List tests = new GsonBuilder().create().fromJson(fileReader, listType); + final var dynamicTests = new ArrayList(); + int i = 0; + for (final MatcherTestImpl test : tests) { + dynamicTests.add(DynamicTest.dynamicTest("Test #" + (i++), test::executeTest)); + } + return dynamicTests; + } + } +} diff --git a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/GrammarTest.java b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/GrammarTest.java deleted file mode 100644 index 2e90abc3d..000000000 --- a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/GrammarTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.grammar; - -import org.eclipse.tm4e.core.internal.grammar.StackElementMetadata; -import org.eclipse.tm4e.core.internal.grammar.StandardTokenType; -import org.eclipse.tm4e.core.theme.FontStyle; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -/** - * {@link StackElementMetadata} tests same than vscode-textmate. - * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/tests/grammar.test.ts - * - */ -public class GrammarTest { - - @Test - public void testWorks() { - int value = StackElementMetadata.set(0, 1, StandardTokenType.RegEx, FontStyle.Underline | FontStyle.Bold, 101, - 102); - assertEquals(value, 1, StandardTokenType.RegEx, FontStyle.Underline | FontStyle.Bold, 101, 102); - } - - @Test - public void testCanOverwriteLanguageId() { - int value = StackElementMetadata.set(0, 1, StandardTokenType.RegEx, FontStyle.Underline | FontStyle.Bold, 101, - 102); - assertEquals(value, 1, StandardTokenType.RegEx, FontStyle.Underline | FontStyle.Bold, 101, 102); - - value = StackElementMetadata.set(value, 2, StandardTokenType.Other, FontStyle.NotSet, 0, 0); - assertEquals(value, 2, StandardTokenType.RegEx, FontStyle.Underline | FontStyle.Bold, 101, 102); - } - - @Test - public void testCanOverwriteTokenType() { - int value = StackElementMetadata.set(0, 1, StandardTokenType.RegEx, FontStyle.Underline | FontStyle.Bold, 101, - 102); - assertEquals(value, 1, StandardTokenType.RegEx, FontStyle.Underline | FontStyle.Bold, 101, 102); - - value = StackElementMetadata.set(value, 0, StandardTokenType.Comment, FontStyle.NotSet, 0, 0); - assertEquals(value, 1, StandardTokenType.Comment, FontStyle.Underline | FontStyle.Bold, 101, 102); - } - - @Test - public void testCanOverwriteFontStyle() { - int value = StackElementMetadata.set(0, 1, StandardTokenType.RegEx, FontStyle.Underline | FontStyle.Bold, 101, - 102); - assertEquals(value, 1, StandardTokenType.RegEx, FontStyle.Underline | FontStyle.Bold, 101, 102); - - value = StackElementMetadata.set(value, 0, StandardTokenType.Other, FontStyle.None, 0, 0); - assertEquals(value, 1, StandardTokenType.RegEx, FontStyle.None, 101, 102); - } - - @Test - public void testCanOverwriteForeground() { - int value = StackElementMetadata.set(0, 1, StandardTokenType.RegEx, FontStyle.Underline | FontStyle.Bold, 101, - 102); - assertEquals(value, 1, StandardTokenType.RegEx, FontStyle.Underline | FontStyle.Bold, 101, 102); - - value = StackElementMetadata.set(value, 0, StandardTokenType.Other, FontStyle.NotSet, 5, 0); - assertEquals(value, 1, StandardTokenType.RegEx, FontStyle.Underline | FontStyle.Bold, 5, 102); - } - - @Test - public void testCanOverwriteBackground() { - int value = StackElementMetadata.set(0, 1, StandardTokenType.RegEx, FontStyle.Underline | FontStyle.Bold, 101, - 102); - assertEquals(value, 1, StandardTokenType.RegEx, FontStyle.Underline | FontStyle.Bold, 101, 102); - - value = StackElementMetadata.set(value, 0, StandardTokenType.Other, FontStyle.NotSet, 0, 7); - assertEquals(value, 1, StandardTokenType.RegEx, FontStyle.Underline | FontStyle.Bold, 101, 7); - } - - @Test - public void testCanWorkAtMaxValues() { - int maxLangId = 255; - int maxTokenType = StandardTokenType.Comment | StandardTokenType.Other | StandardTokenType.RegEx - | StandardTokenType.String; - int maxFontStyle = FontStyle.Bold | FontStyle.Italic | FontStyle.Underline; - int maxForeground = 511; - int maxBackground = 511; - - int value = StackElementMetadata.set(0, maxLangId, maxTokenType, maxFontStyle, maxForeground, maxBackground); - assertEquals(value, maxLangId, maxTokenType, maxFontStyle, maxForeground, maxBackground); - } - - private static void assertEquals(int metadata, int languageId, int tokenType, int fontStyle, int foreground, int background) { - String actual = "{\n" + - "languageId: " + StackElementMetadata.getLanguageId(metadata) + ",\n" + - "tokenType: " + StackElementMetadata.getTokenType(metadata) + ",\n" + - "fontStyle: " + StackElementMetadata.getFontStyle(metadata) + ",\n" + - "foreground: " + StackElementMetadata.getForeground(metadata) + ",\n" + - "background: " + StackElementMetadata.getBackground(metadata) + ",\n" + - "}"; - - String expected = "{\n" + - "languageId: " + languageId + ",\n" + - "tokenType: " + tokenType + ",\n" + - "fontStyle: " + fontStyle + ",\n" + - "foreground: " + foreground + ",\n" + - "background: " + background + ",\n" + - "}"; - - Assertions.assertEquals(expected, actual, "equals for " + StackElementMetadata.toBinaryStr(metadata)); - } -} diff --git a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/internal/MatcherTestImpl.java b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/internal/MatcherTestImpl.java index 4bedf4fd2..813720055 100644 --- a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/internal/MatcherTestImpl.java +++ b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/internal/MatcherTestImpl.java @@ -1,38 +1,38 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.grammar.internal; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.util.Collection; -import java.util.List; - -import org.eclipse.tm4e.core.internal.matcher.Matcher; -import org.eclipse.tm4e.core.internal.matcher.MatcherWithPriority; - -public class MatcherTestImpl { - - private String expression; - private List input; - private boolean result; - - public MatcherTestImpl() { - } - - - public void executeTest() { - Collection>> matcher = Matcher.createMatchers(expression); - boolean result = matcher.stream().anyMatch(m -> m.matcher.test(input)); - assertEquals(result, this.result); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.grammar.internal; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Collection; +import java.util.List; + +import org.eclipse.tm4e.core.internal.matcher.Matcher; +import org.eclipse.tm4e.core.internal.matcher.MatcherWithPriority; + +public class MatcherTestImpl { + + private String expression; + private List input; + private boolean result; + + public MatcherTestImpl() { + } + + + public void executeTest() { + Collection>> matcher = Matcher.createMatchers(expression); + boolean result = matcher.stream().anyMatch(m -> m.matcher.matches(input)); + assertEquals(result, this.result); + } + +} diff --git a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/internal/RawTestImpl.java b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/internal/RawTestImpl.java index 90189bb06..8685757f6 100644 --- a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/internal/RawTestImpl.java +++ b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/internal/RawTestImpl.java @@ -1,160 +1,169 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.grammar.internal; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; - -import org.eclipse.tm4e.core.grammar.IGrammar; -import org.eclipse.tm4e.core.grammar.IToken; -import org.eclipse.tm4e.core.grammar.ITokenizeLineResult; -import org.eclipse.tm4e.core.grammar.StackElement; -import org.eclipse.tm4e.core.registry.IRegistryOptions; -import org.eclipse.tm4e.core.registry.Registry; - -public class RawTestImpl { - - private String desc; - private List grammars; - private String grammarPath; - private String grammarScopeName; - private List grammarInjections; - private List lines; - private File testLocation; - - public String getDesc() { - return desc; - } - - public List getGrammars() { - return grammars; - } - - public String getGrammarPath() { - return grammarPath; - } - - public String getGrammarScopeName() { - return grammarScopeName; - } - - public List getGrammarInjections() { - return grammarInjections; - } - - public List getLines() { - return lines; - } - - public void executeTest() throws Exception { - IRegistryOptions locator = new IRegistryOptions() { - - @Override - public String getFilePath(String scopeName) { - return null; - } - - @Override - public InputStream getInputStream(String scopeName) throws IOException { - return null; - } - - @Override - public Collection getInjections(String scopeName) { - if (scopeName.equals(getGrammarScopeName())) { - return getGrammarInjections(); - } - return null; - } - }; - - Registry registry = new Registry(locator); - IGrammar grammar = getGrammar(registry, testLocation.getParentFile()); - - if (getGrammarScopeName() != null) { - grammar = registry.grammarForScopeName(getGrammarScopeName()); - } - - if (grammar == null) { - throw new Exception("I HAVE NO GRAMMAR FOR TEST"); - } - - StackElement prevState = null; - for (RawTestLine testLine : getLines()) { - prevState = assertLineTokenization(grammar, testLine, prevState); - } - } - - private IGrammar getGrammar(Registry registry, File testLocation) throws Exception { - IGrammar grammar = null; - for (String grammarPath : getGrammars()) { - IGrammar tmpGrammar = registry.loadGrammarFromPathSync(new File(testLocation, grammarPath)); - if (grammarPath.equals(getGrammarPath())) { - grammar = tmpGrammar; - } - } - return grammar; - } - - private static StackElement assertLineTokenization(IGrammar grammar, RawTestLine testCase, StackElement prevState) { - ITokenizeLineResult actual = grammar.tokenizeLine(testCase.getLine(), prevState); - - List actualTokens = getActualTokens(actual.getTokens(), testCase); - - List expectedTokens = testCase.getTokens(); - // // TODO@Alex: fix tests instead of working around - if (testCase.getLine().length() > 0) { - // Remove empty tokens... - expectedTokens = testCase.getTokens().stream().filter(token -> token.getValue().length() > 0) - .collect(Collectors.toList()); - } - deepEqual(actualTokens, expectedTokens, "Tokenizing line '" + testCase.getLine() + "'"); - - return actual.getRuleStack(); - } - - private static void deepEqual(List actualTokens, List expextedTokens, String message) { - // compare collection size - assertEquals(expextedTokens.size(), actualTokens.size(), message + " (collection size problem)"); - // compare item - for (int i = 0; i < expextedTokens.size(); i++) { - RawToken expected = expextedTokens.get(i); - RawToken actual = actualTokens.get(i); - assertEquals(expected.getValue(), actual.getValue(), message + " (value of item '" + i + "' problem)"); - assertEquals(expected.getScopes(), actual.getScopes(), message + " (tokens of item '" + i + "' problem)"); - } - - } - - private static List getActualTokens(IToken[] tokens, RawTestLine testCase) { - List actualTokens = new ArrayList<>(); - for (IToken token : tokens) { - String value = testCase.getLine().substring(token.getStartIndex(), - token.getEndIndex() < testCase.getLine().length() ? token.getEndIndex() - : testCase.getLine().length()); - actualTokens.add(new RawToken(value, token.getScopes())); - } - return actualTokens; - } - - public void setTestLocation(File testLocation) { - this.testLocation = testLocation; - } - -} +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.grammar.internal; + +import static java.util.stream.Collectors.*; +import static org.junit.jupiter.api.Assertions.*; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import org.eclipse.tm4e.core.grammar.IGrammar; +import org.eclipse.tm4e.core.grammar.IStackElement; +import org.eclipse.tm4e.core.registry.IRegistryOptions; +import org.eclipse.tm4e.core.registry.Registry; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/tests/tokenization.tests.ts + */ +public class RawTestImpl { + + private static final class RawTestLine { + String line; + List tokens; + } + + private String desc; + private List grammars; + private String grammarPath; + private String grammarScopeName; + private List grammarInjections; + private List lines; + private File testLocation; + + public String getDesc() { + return desc; + } + + public List getGrammars() { + return grammars; + } + + public String getGrammarPath() { + return grammarPath; + } + + public String getGrammarScopeName() { + return grammarScopeName; + } + + public List getGrammarInjections() { + return grammarInjections; + } + + public List getLines() { + return lines; + } + + public void executeTest() throws Exception { + final var options = new IRegistryOptions() { + + @Override + public String getFilePath(final String scopeName) { + return null; + } + + @Override + public InputStream getInputStream(final String scopeName) throws IOException { + return null; + } + + @Override + public Collection getInjections(final String scopeName) { + if (scopeName.equals(getGrammarScopeName())) { + return getGrammarInjections(); + } + return null; + } + }; + + final Registry registry = new Registry(options); + IGrammar grammar = getGrammar(registry, testLocation.getParentFile()); + if (getGrammarScopeName() != null) { + grammar = registry.grammarForScopeName(getGrammarScopeName()); + } + if (grammar == null) { + throw new Exception("I HAVE NO GRAMMAR FOR TEST"); + } + + IStackElement prevState = null; + for (final var testLine : lines) { + prevState = assertLineTokenization(grammar, testLine, prevState); + } + } + + private IGrammar getGrammar(final Registry registry, final File testLocation) throws Exception { + IGrammar grammar = null; + for (final String grammarPath : getGrammars()) { + final IGrammar tmpGrammar = registry.loadGrammarFromPathSync(new File(testLocation, grammarPath)); + if (grammarPath.equals(getGrammarPath())) { + grammar = tmpGrammar; + } + } + return grammar; + } + + private static IStackElement assertLineTokenization(final IGrammar grammar, final RawTestLine testCase, + final IStackElement prevState) { + final var line = testCase.line; + final var actual = grammar.tokenizeLine(line, prevState); + + final var actualTokens = Arrays.stream(actual.getTokens()) + .map(token -> new RawToken( + line.substring( + token.getStartIndex(), + Math.min(token.getEndIndex(), line.length())), // TODO Math.min not required in upstream why? + token.getScopes())) + .collect(toList()); + + // TODO@Alex: fix tests instead of working around + if (!line.isEmpty()) { + // Remove empty tokens... + testCase.tokens = testCase.tokens.stream().filter(token -> !token.getValue().isEmpty()).collect(toList()); + } + + deepEqual(actualTokens, testCase.tokens, "Tokenizing line '" + line + "'"); + + return actual.getRuleStack(); + } + + private static void deepEqual(final List actualTokens, final List expextedTokens, + final String message) { + + // compare collection size + if (expextedTokens.size() != actualTokens.size()) { + final var actualTokensStr = actualTokens.stream().map(Object::toString).collect(joining("\n")); + final var expextedTokensStr = expextedTokens.stream().map(Object::toString).collect(joining("\n")); + + assertEquals(expextedTokensStr, actualTokensStr, + message + " (collection size problem: actual=" + actualTokens.size() + " expected=" + + expextedTokens.size() + ")"); + } + + // compare item + for (int i = 0; i < expextedTokens.size(); i++) { + final var expected = expextedTokens.get(i); + final var actual = actualTokens.get(i); + assertEquals(expected.getValue(), actual.getValue(), message + " (value of item '" + i + "' problem)"); + assertEquals(expected.getScopes(), actual.getScopes(), message + " (tokens of item '" + i + "' problem)"); + } + } + + public void setTestLocation(final File testLocation) { + this.testLocation = testLocation; + } +} diff --git a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/internal/RawTestLine.java b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/internal/RawTestLine.java deleted file mode 100644 index ea02dec23..000000000 --- a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/internal/RawTestLine.java +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.grammar.internal; - -import java.util.List; - -public class RawTestLine { - - private String line; - private List tokens; - - public String getLine() { - return line; - } - - public List getTokens() { - return tokens; - } -} diff --git a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/internal/RawToken.java b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/internal/RawToken.java index 7934f68f8..211c3550a 100644 --- a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/internal/RawToken.java +++ b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/grammar/internal/RawToken.java @@ -1,48 +1,62 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.grammar.internal; - -import java.util.List; - -public class RawToken { - - private String value; - private List scopes; - - public RawToken() { - } - - public RawToken(String value, List scopes) { - this.value = value; - this.scopes = scopes; - } - - public String getValue() { - return value; - } - - public List getScopes() { - return scopes; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof RawToken)) { - return false; - } - RawToken other = (RawToken) obj; - if (!(this.value.equals(other.value))) { - return false; - } - return this.scopes.equals(other.scopes); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.grammar.internal; + +import java.util.List; + +public class RawToken { + + private String value; + private List scopes; + + public RawToken() { + } + + public RawToken(String value, List scopes) { + this.value = value; + this.scopes = scopes; + } + + public String getValue() { + return value; + } + + public List getScopes() { + return scopes; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof RawToken)) { + return false; + } + RawToken other = (RawToken) obj; + if (!(this.value.equals(other.value))) { + return false; + } + return this.scopes.equals(other.scopes); + } + + @Override + public int hashCode() { + final var prime = 31; + var result = 1; + result = prime * result + (scopes == null ? 0 : scopes.hashCode()); + result = prime * result + (value == null ? 0 : value.hashCode()); + return result; + } + + @Override + public String toString() { + return "RawToken{\n value:" + value + "\n scopes:" + scopes + "\n}"; + } +} diff --git a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/theme/ThemeMatchingTest.java b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeMatchingTest.java similarity index 91% rename from org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/theme/ThemeMatchingTest.java rename to org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeMatchingTest.java index c7bc7b632..b763b5dbd 100644 --- a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/theme/ThemeMatchingTest.java +++ b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeMatchingTest.java @@ -1,275 +1,274 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.theme; - -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.ByteArrayInputStream; -import java.util.Arrays; -import java.util.List; - -import org.eclipse.tm4e.core.internal.grammar.ScopeListElement; -import org.eclipse.tm4e.core.internal.grammar.ScopeMetadata; -import org.eclipse.tm4e.core.internal.grammar.StackElementMetadata; -import org.eclipse.tm4e.core.internal.theme.reader.ThemeReader; -import org.junit.jupiter.api.Test; - -/** - * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/tests/themes.test.ts - * - */ -class ThemeMatchingTest { - - @Test - void testGivesHigherPriorityToDeeperMatches() throws Exception { - Theme theme = loadTheme("{" + - "\"settings\": ["+ - "{ \"settings\": { \"foreground\": \"#100000\", \"background\": \"#200000\" } },"+ - "{ \"scope\": \"punctuation.definition.string.begin.html\", \"settings\": { \"foreground\": \"#300000\" } },"+ - "{ \"scope\": \"meta.tag punctuation.definition.string\", \"settings\": { \"foreground\": \"#400000\" } }"+ - "]"+ - "}"); - - - ColorMap colorMap = new ColorMap(); - int _NOT_SET = 0; - int _A = colorMap.getId("#100000"); - int _B = colorMap.getId("#200000"); - int _C = colorMap.getId("#400000"); - int _D = colorMap.getId("#300000"); - - List actual = theme.match("punctuation.definition.string.begin.html"); - - assertArrayEquals( - new ThemeTrieElementRule[] { new ThemeTrieElementRule(5, null, FontStyle.NotSet, _D, _NOT_SET), - new ThemeTrieElementRule(3, Arrays.asList("meta.tag"), FontStyle.NotSet, _C, _NOT_SET) }, - actual.toArray()); - } - - @Test - void testGivesHigherPriorityToParentMatches1() throws Exception { - Theme theme = loadTheme("{" + - "\"settings\": ["+ - "{ \"settings\": { \"foreground\": \"#100000\", \"background\": \"#200000\" } },"+ - "{ \"scope\": \"c a\", \"settings\": { \"foreground\": \"#300000\" } },"+ - "{ \"scope\": \"d a.b\", \"settings\": { \"foreground\": \"#400000\" } },"+ - "{ \"scope\": \"a\", \"settings\": { \"foreground\": \"#500000\" } }"+ - "]"+ - "}"); - - - ColorMap colorMap = new ColorMap(); - int _NOT_SET = 0; - int _A = colorMap.getId("#100000"); - int _B = colorMap.getId("#200000"); - int _C = colorMap.getId("#500000"); - int _D = colorMap.getId("#300000"); - int _E = colorMap.getId("#400000"); - - List actual = theme.match("a.b"); - - assertArrayEquals(new ThemeTrieElementRule[] { - new ThemeTrieElementRule(2, Arrays.asList("d"), FontStyle.NotSet, _E, _NOT_SET), - new ThemeTrieElementRule(1, Arrays.asList("c"), FontStyle.NotSet, _D, _NOT_SET), - new ThemeTrieElementRule(1, null, FontStyle.NotSet, _C, _NOT_SET) }, actual.toArray()); - } - - @Test - void testGivesHigherPriorityToParentMatches2() throws Exception { - Theme theme = loadTheme("{" + - "\"settings\": ["+ - "{ \"settings\": { \"foreground\": \"#100000\", \"background\": \"#200000\" } },"+ - "{ \"scope\": \"meta.tag entity\", \"settings\": { \"foreground\": \"#300000\" } },"+ - "{ \"scope\": \"meta.selector.css entity.name.tag\", \"settings\": { \"foreground\": \"#400000\" } },"+ - "{ \"scope\": \"entity\", \"settings\": { \"foreground\": \"#500000\" } }"+ - "]"+ - "}"); - - - ScopeListElement root = new ScopeListElement(null, "text.html.cshtml", 0); - ScopeListElement parent = new ScopeListElement(root, "meta.tag.structure.any.html", 0); - int r = ScopeListElement.mergeMetadata(0, parent, new ScopeMetadata("entity.name.tag.structure.any.html", 0, 0, - theme.match("entity.name.tag.structure.any.html"))); - String color = theme.getColor(StackElementMetadata.getForeground(r)); - assertEquals("#300000", color); - } - - @Test - void testCanMatch() throws Exception { - Theme theme = loadTheme("{" + - "\"settings\": ["+ - "{ \"settings\": { \"foreground\": \"#F8F8F2\", \"background\": \"#272822\" } },"+ - "{ \"scope\": \"source, something\", \"settings\": { \"background\": \"#100000\" } },"+ - "{ \"scope\": [\"bar\", \"baz\"], \"settings\": { \"background\": \"#200000\" } },"+ - "{ \"scope\": \"source.css selector bar\", \"settings\": { \"fontStyle\": \"bold\" } },"+ - "{ \"scope\": \"constant\", \"settings\": { \"fontStyle\": \"italic\", \"foreground\": \"#300000\" } },"+ - "{ \"scope\": \"constant.numeric\", \"settings\": { \"foreground\": \"#400000\" } },"+ - "{ \"scope\": \"constant.numeric.hex\", \"settings\": { \"fontStyle\": \"bold\" } },"+ - "{ \"scope\": \"constant.numeric.oct\", \"settings\": { \"fontStyle\": \"bold italic underline\" } },"+ - "{ \"scope\": \"constant.numeric.dec\", \"settings\": { \"fontStyle\": \"\", \"foreground\": \"#500000\" } },"+ - "{ \"scope\": \"storage.object.bar\", \"settings\": { \"fontStyle\": \"\", \"foreground\": \"#600000\" } }"+ - "]"+ - "}"); - - ColorMap colorMap = new ColorMap(); - int _NOT_SET = 0; - int _A = colorMap.getId("#F8F8F2"); - int _B = colorMap.getId("#272822"); - int _C = colorMap.getId("#200000"); - int _D = colorMap.getId("#300000"); - int _E = colorMap.getId("#400000"); - int _F = colorMap.getId("#500000"); - int _G = colorMap.getId("#100000"); - int _H = colorMap.getId("#600000"); - - // matches defaults - assertNoMatch(theme, ""); - assertNoMatch(theme, "bazz"); - assertNoMatch(theme, "asdfg"); - - // matches source - assertSimpleMatch(theme, "source", 1, FontStyle.NotSet, _NOT_SET, _G); - assertSimpleMatch(theme, "source.ts", 1, FontStyle.NotSet, _NOT_SET, _G); - assertSimpleMatch(theme, "source.tss", 1, FontStyle.NotSet, _NOT_SET, _G); - - // matches something - assertSimpleMatch(theme, "something", 1, FontStyle.NotSet, _NOT_SET, _G); - assertSimpleMatch(theme, "something.ts", 1, FontStyle.NotSet, _NOT_SET, _G); - assertSimpleMatch(theme, "something.tss", 1, FontStyle.NotSet, _NOT_SET, _G); - - // matches baz - assertSimpleMatch(theme, "baz", 1, FontStyle.NotSet, _NOT_SET, _C); - assertSimpleMatch(theme, "baz.ts", 1, FontStyle.NotSet, _NOT_SET, _C); - assertSimpleMatch(theme, "baz.tss", 1, FontStyle.NotSet, _NOT_SET, _C); - - // matches constant - assertSimpleMatch(theme, "constant", 1, FontStyle.Italic, _D, _NOT_SET); - assertSimpleMatch(theme, "constant.string", 1, FontStyle.Italic, _D, _NOT_SET); - assertSimpleMatch(theme, "constant.hex", 1, FontStyle.Italic, _D, _NOT_SET); - - // matches constant.numeric - assertSimpleMatch(theme, "constant.numeric", 2, FontStyle.Italic, _E, _NOT_SET); - assertSimpleMatch(theme, "constant.numeric.baz", 2, FontStyle.Italic, _E, _NOT_SET); - - // matches constant.numeric.hex - assertSimpleMatch(theme, "constant.numeric.hex", 3, FontStyle.Bold, _E, _NOT_SET); - assertSimpleMatch(theme, "constant.numeric.hex.baz", 3, FontStyle.Bold, _E, _NOT_SET); - - // matches constant.numeric.oct - assertSimpleMatch(theme, "constant.numeric.oct", 3, FontStyle.Bold | FontStyle.Italic | FontStyle.Underline, _E, - _NOT_SET); - assertSimpleMatch(theme, "constant.numeric.oct.baz", 3, FontStyle.Bold | FontStyle.Italic | FontStyle.Underline, - _E, _NOT_SET); - - // matches constant.numeric.dec - assertSimpleMatch(theme, "constant.numeric.dec", 3, FontStyle.None, _F, _NOT_SET); - assertSimpleMatch(theme, "constant.numeric.dec.baz", 3, FontStyle.None, _F, _NOT_SET); - - // matches storage.object.bar - assertSimpleMatch(theme, "storage.object.bar", 3, FontStyle.None, _H, _NOT_SET); - assertSimpleMatch(theme, "storage.object.bar.baz", 3, FontStyle.None, _H, _NOT_SET); - - // does not match storage.object.bar - assertSimpleMatch(theme, "storage.object.bart", 0, FontStyle.NotSet, _NOT_SET, _NOT_SET); - assertSimpleMatch(theme, "storage.object", 0, FontStyle.NotSet, _NOT_SET, _NOT_SET); - assertSimpleMatch(theme, "storage", 0, FontStyle.NotSet, _NOT_SET, _NOT_SET); - - assertMatch(theme, "bar", - new ThemeTrieElementRule[] { new ThemeTrieElementRule(1, Arrays.asList("selector", "source.css"), - FontStyle.Bold, _NOT_SET, _C), - new ThemeTrieElementRule(1, null, FontStyle.NotSet, _NOT_SET, _C) }); - } - - @Test - void testMicrosoft_vscode_23460() throws Exception { - Theme theme = loadTheme("{" + - "\"settings\": ["+ - "{" + - "\"settings\": {"+ - "\"foreground\": \"#aec2e0\","+ - "\"background\": \"#14191f\""+ - "}"+ - "}, {"+ - "\"name\": \"JSON String\","+ - "\"scope\": \"meta.structure.dictionary.json string.quoted.double.json\","+ - "\"settings\": {"+ - "\"foreground\": \"#FF410D\""+ - "}"+ - "}, {"+ - "\"scope\": \"meta.structure.dictionary.json string.quoted.double.json\","+ - "\"settings\": {"+ - "\"foreground\": \"#ffffff\""+ - "}"+ - "},"+ - "{"+ - "\"scope\": \"meta.structure.dictionary.value.json string.quoted.double.json\","+ - "\"settings\": {"+ - "\"foreground\": \"#FF410D\""+ - "}"+ - "}"+ - "]"+ - "}"); - - ColorMap colorMap = new ColorMap(); - int _NOT_SET = 0; - int _A = colorMap.getId("#aec2e0"); - int _B = colorMap.getId("#14191f"); - int _C = colorMap.getId("#FF410D"); - int _D = colorMap.getId("#ffffff"); - - - // string.quoted.double.json - // meta.structure.dictionary.value.json - // meta.structure.dictionary.json - // source.json - assertMatch(theme, "string.quoted.double.json", new ThemeTrieElementRule[] { - new ThemeTrieElementRule(4, Arrays.asList("meta.structure.dictionary.value.json"), FontStyle.NotSet, _C, _NOT_SET), - new ThemeTrieElementRule(4, Arrays.asList("meta.structure.dictionary.json"), FontStyle.NotSet, _D, _NOT_SET), - new ThemeTrieElementRule(0, null, FontStyle.NotSet, _NOT_SET, _NOT_SET) - }); - - ScopeListElement parent3 = new ScopeListElement(null, "source.json", 0); - ScopeListElement parent2 = new ScopeListElement(parent3, "meta.structure.dictionary.json", 0); - ScopeListElement parent1 = new ScopeListElement(parent2, "meta.structure.dictionary.value.json", 0); - - int r = ScopeListElement.mergeMetadata( - 0, - parent1, - new ScopeMetadata("string.quoted.double.json", 0, 0, theme.match("string.quoted.double.json")) - ); - String color = theme.getColor(StackElementMetadata.getForeground(r)); - assertEquals("#FF410D", color); - } - - private void assertMatch(Theme theme, String scopeName, ThemeTrieElementRule[] expected) { - List actual = theme.match(scopeName); - assertArrayEquals(expected, actual.toArray(), "when matching <<" + scopeName + ">>"); - } - - private void assertSimpleMatch(Theme theme, String scopeName, int scopeDepth, int fontStyle, int foreground, int background) { - assertMatch(theme, scopeName, new ThemeTrieElementRule [] { - new ThemeTrieElementRule(scopeDepth, null, fontStyle, foreground, background) - }); - } - - private void assertNoMatch(Theme theme, String scopeName) { - assertMatch(theme, scopeName, new ThemeTrieElementRule [] { - new ThemeTrieElementRule(0, null, FontStyle.NotSet, 0, 0 /*_NOT_SET, _NOT_SET*/) - }); - } - - private Theme loadTheme(String theme) throws Exception { - return Theme.createFromRawTheme(ThemeReader.JSON_PARSER.parse(new ByteArrayInputStream(theme.getBytes()))); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.ByteArrayInputStream; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.tm4e.core.internal.grammar.ScopeListElement; +import org.eclipse.tm4e.core.internal.grammar.ScopeMetadata; +import org.eclipse.tm4e.core.internal.grammar.StackElementMetadata; +import org.eclipse.tm4e.core.internal.theme.reader.ThemeReader; +import org.junit.jupiter.api.Test; + +/** + * + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/tests/themes.test.ts + * + */ +class ThemeMatchingTest { + + @Test + void testGivesHigherPriorityToDeeperMatches() throws Exception { + Theme theme = loadTheme("{" + + "\"settings\": ["+ + "{ \"settings\": { \"foreground\": \"#100000\", \"background\": \"#200000\" } },"+ + "{ \"scope\": \"punctuation.definition.string.begin.html\", \"settings\": { \"foreground\": \"#300000\" } },"+ + "{ \"scope\": \"meta.tag punctuation.definition.string\", \"settings\": { \"foreground\": \"#400000\" } }"+ + "]"+ + "}"); + + + ColorMap colorMap = new ColorMap(); + int _NOT_SET = 0; + int _A = colorMap.getId("#100000"); + int _B = colorMap.getId("#200000"); + int _C = colorMap.getId("#400000"); + int _D = colorMap.getId("#300000"); + + List actual = theme.match("punctuation.definition.string.begin.html"); + + assertArrayEquals( + new ThemeTrieElementRule[] { new ThemeTrieElementRule(5, null, FontStyle.NotSet, _D, _NOT_SET), + new ThemeTrieElementRule(3, Arrays.asList("meta.tag"), FontStyle.NotSet, _C, _NOT_SET) }, + actual.toArray()); + } + + @Test + void testGivesHigherPriorityToParentMatches1() throws Exception { + Theme theme = loadTheme("{" + + "\"settings\": ["+ + "{ \"settings\": { \"foreground\": \"#100000\", \"background\": \"#200000\" } },"+ + "{ \"scope\": \"c a\", \"settings\": { \"foreground\": \"#300000\" } },"+ + "{ \"scope\": \"d a.b\", \"settings\": { \"foreground\": \"#400000\" } },"+ + "{ \"scope\": \"a\", \"settings\": { \"foreground\": \"#500000\" } }"+ + "]"+ + "}"); + + + ColorMap colorMap = new ColorMap(); + int _NOT_SET = 0; + int _A = colorMap.getId("#100000"); + int _B = colorMap.getId("#200000"); + int _C = colorMap.getId("#500000"); + int _D = colorMap.getId("#300000"); + int _E = colorMap.getId("#400000"); + + List actual = theme.match("a.b"); + + assertArrayEquals(new ThemeTrieElementRule[] { + new ThemeTrieElementRule(2, Arrays.asList("d"), FontStyle.NotSet, _E, _NOT_SET), + new ThemeTrieElementRule(1, Arrays.asList("c"), FontStyle.NotSet, _D, _NOT_SET), + new ThemeTrieElementRule(1, null, FontStyle.NotSet, _C, _NOT_SET) }, actual.toArray()); + } + + @Test + void testGivesHigherPriorityToParentMatches2() throws Exception { + Theme theme = loadTheme("{" + + "\"settings\": ["+ + "{ \"settings\": { \"foreground\": \"#100000\", \"background\": \"#200000\" } },"+ + "{ \"scope\": \"meta.tag entity\", \"settings\": { \"foreground\": \"#300000\" } },"+ + "{ \"scope\": \"meta.selector.css entity.name.tag\", \"settings\": { \"foreground\": \"#400000\" } },"+ + "{ \"scope\": \"entity\", \"settings\": { \"foreground\": \"#500000\" } }"+ + "]"+ + "}"); + + + ScopeListElement root = new ScopeListElement(null, "text.html.cshtml", 0); + ScopeListElement parent = new ScopeListElement(root, "meta.tag.structure.any.html", 0); + int r = ScopeListElement.mergeMetadata(0, parent, new ScopeMetadata("entity.name.tag.structure.any.html", 0, 0, + theme.match("entity.name.tag.structure.any.html"))); + String color = theme.getColor(StackElementMetadata.getForeground(r)); + assertEquals("#300000", color); + } + + @Test + void testCanMatch() throws Exception { + Theme theme = loadTheme("{" + + "\"settings\": ["+ + "{ \"settings\": { \"foreground\": \"#F8F8F2\", \"background\": \"#272822\" } },"+ + "{ \"scope\": \"source, something\", \"settings\": { \"background\": \"#100000\" } },"+ + "{ \"scope\": [\"bar\", \"baz\"], \"settings\": { \"background\": \"#200000\" } },"+ + "{ \"scope\": \"source.css selector bar\", \"settings\": { \"fontStyle\": \"bold\" } },"+ + "{ \"scope\": \"constant\", \"settings\": { \"fontStyle\": \"italic\", \"foreground\": \"#300000\" } },"+ + "{ \"scope\": \"constant.numeric\", \"settings\": { \"foreground\": \"#400000\" } },"+ + "{ \"scope\": \"constant.numeric.hex\", \"settings\": { \"fontStyle\": \"bold\" } },"+ + "{ \"scope\": \"constant.numeric.oct\", \"settings\": { \"fontStyle\": \"bold italic underline\" } },"+ + "{ \"scope\": \"constant.numeric.dec\", \"settings\": { \"fontStyle\": \"\", \"foreground\": \"#500000\" } },"+ + "{ \"scope\": \"storage.object.bar\", \"settings\": { \"fontStyle\": \"\", \"foreground\": \"#600000\" } }"+ + "]"+ + "}"); + + ColorMap colorMap = new ColorMap(); + int _NOT_SET = 0; + int _A = colorMap.getId("#F8F8F2"); + int _B = colorMap.getId("#272822"); + int _C = colorMap.getId("#200000"); + int _D = colorMap.getId("#300000"); + int _E = colorMap.getId("#400000"); + int _F = colorMap.getId("#500000"); + int _G = colorMap.getId("#100000"); + int _H = colorMap.getId("#600000"); + + // matches defaults + assertNoMatch(theme, ""); + assertNoMatch(theme, "bazz"); + assertNoMatch(theme, "asdfg"); + + // matches source + assertSimpleMatch(theme, "source", 1, FontStyle.NotSet, _NOT_SET, _G); + assertSimpleMatch(theme, "source.ts", 1, FontStyle.NotSet, _NOT_SET, _G); + assertSimpleMatch(theme, "source.tss", 1, FontStyle.NotSet, _NOT_SET, _G); + + // matches something + assertSimpleMatch(theme, "something", 1, FontStyle.NotSet, _NOT_SET, _G); + assertSimpleMatch(theme, "something.ts", 1, FontStyle.NotSet, _NOT_SET, _G); + assertSimpleMatch(theme, "something.tss", 1, FontStyle.NotSet, _NOT_SET, _G); + + // matches baz + assertSimpleMatch(theme, "baz", 1, FontStyle.NotSet, _NOT_SET, _C); + assertSimpleMatch(theme, "baz.ts", 1, FontStyle.NotSet, _NOT_SET, _C); + assertSimpleMatch(theme, "baz.tss", 1, FontStyle.NotSet, _NOT_SET, _C); + + // matches constant + assertSimpleMatch(theme, "constant", 1, FontStyle.Italic, _D, _NOT_SET); + assertSimpleMatch(theme, "constant.string", 1, FontStyle.Italic, _D, _NOT_SET); + assertSimpleMatch(theme, "constant.hex", 1, FontStyle.Italic, _D, _NOT_SET); + + // matches constant.numeric + assertSimpleMatch(theme, "constant.numeric", 2, FontStyle.Italic, _E, _NOT_SET); + assertSimpleMatch(theme, "constant.numeric.baz", 2, FontStyle.Italic, _E, _NOT_SET); + + // matches constant.numeric.hex + assertSimpleMatch(theme, "constant.numeric.hex", 3, FontStyle.Bold, _E, _NOT_SET); + assertSimpleMatch(theme, "constant.numeric.hex.baz", 3, FontStyle.Bold, _E, _NOT_SET); + + // matches constant.numeric.oct + assertSimpleMatch(theme, "constant.numeric.oct", 3, FontStyle.Bold | FontStyle.Italic | FontStyle.Underline, _E, + _NOT_SET); + assertSimpleMatch(theme, "constant.numeric.oct.baz", 3, FontStyle.Bold | FontStyle.Italic | FontStyle.Underline, + _E, _NOT_SET); + + // matches constant.numeric.dec + assertSimpleMatch(theme, "constant.numeric.dec", 3, FontStyle.None, _F, _NOT_SET); + assertSimpleMatch(theme, "constant.numeric.dec.baz", 3, FontStyle.None, _F, _NOT_SET); + + // matches storage.object.bar + assertSimpleMatch(theme, "storage.object.bar", 3, FontStyle.None, _H, _NOT_SET); + assertSimpleMatch(theme, "storage.object.bar.baz", 3, FontStyle.None, _H, _NOT_SET); + + // does not match storage.object.bar + assertSimpleMatch(theme, "storage.object.bart", 0, FontStyle.NotSet, _NOT_SET, _NOT_SET); + assertSimpleMatch(theme, "storage.object", 0, FontStyle.NotSet, _NOT_SET, _NOT_SET); + assertSimpleMatch(theme, "storage", 0, FontStyle.NotSet, _NOT_SET, _NOT_SET); + + assertMatch(theme, "bar", + new ThemeTrieElementRule[] { new ThemeTrieElementRule(1, Arrays.asList("selector", "source.css"), + FontStyle.Bold, _NOT_SET, _C), + new ThemeTrieElementRule(1, null, FontStyle.NotSet, _NOT_SET, _C) }); + } + + @Test + void testMicrosoft_vscode_23460() throws Exception { + Theme theme = loadTheme("{" + + "\"settings\": ["+ + "{" + + "\"settings\": {"+ + "\"foreground\": \"#aec2e0\","+ + "\"background\": \"#14191f\""+ + "}"+ + "}, {"+ + "\"name\": \"JSON String\","+ + "\"scope\": \"meta.structure.dictionary.json string.quoted.double.json\","+ + "\"settings\": {"+ + "\"foreground\": \"#FF410D\""+ + "}"+ + "}, {"+ + "\"scope\": \"meta.structure.dictionary.json string.quoted.double.json\","+ + "\"settings\": {"+ + "\"foreground\": \"#ffffff\""+ + "}"+ + "},"+ + "{"+ + "\"scope\": \"meta.structure.dictionary.value.json string.quoted.double.json\","+ + "\"settings\": {"+ + "\"foreground\": \"#FF410D\""+ + "}"+ + "}"+ + "]"+ + "}"); + + ColorMap colorMap = new ColorMap(); + int _NOT_SET = 0; + int _A = colorMap.getId("#aec2e0"); + int _B = colorMap.getId("#14191f"); + int _C = colorMap.getId("#FF410D"); + int _D = colorMap.getId("#ffffff"); + + // string.quoted.double.json + // meta.structure.dictionary.value.json + // meta.structure.dictionary.json + // source.json + assertMatch(theme, "string.quoted.double.json", new ThemeTrieElementRule[] { + new ThemeTrieElementRule(4, Arrays.asList("meta.structure.dictionary.value.json"), FontStyle.NotSet, _C, _NOT_SET), + new ThemeTrieElementRule(4, Arrays.asList("meta.structure.dictionary.json"), FontStyle.NotSet, _D, _NOT_SET), + new ThemeTrieElementRule(0, null, FontStyle.NotSet, _NOT_SET, _NOT_SET) + }); + + ScopeListElement parent3 = new ScopeListElement(null, "source.json", 0); + ScopeListElement parent2 = new ScopeListElement(parent3, "meta.structure.dictionary.json", 0); + ScopeListElement parent1 = new ScopeListElement(parent2, "meta.structure.dictionary.value.json", 0); + + int r = ScopeListElement.mergeMetadata( + 0, + parent1, + new ScopeMetadata("string.quoted.double.json", 0, 0, theme.match("string.quoted.double.json")) + ); + String color = theme.getColor(StackElementMetadata.getForeground(r)); + assertEquals("#FF410D", color); + } + + private void assertMatch(Theme theme, String scopeName, ThemeTrieElementRule[] expected) { + List actual = theme.match(scopeName); + assertArrayEquals(expected, actual.toArray(), "when matching <<" + scopeName + ">>"); + } + + private void assertSimpleMatch(Theme theme, String scopeName, int scopeDepth, int fontStyle, int foreground, int background) { + assertMatch(theme, scopeName, new ThemeTrieElementRule [] { + new ThemeTrieElementRule(scopeDepth, null, fontStyle, foreground, background) + }); + } + + private void assertNoMatch(Theme theme, String scopeName) { + assertMatch(theme, scopeName, new ThemeTrieElementRule [] { + new ThemeTrieElementRule(0, null, FontStyle.NotSet, 0, 0 /*_NOT_SET, _NOT_SET*/) + }); + } + + private Theme loadTheme(String theme) throws Exception { + return Theme.createFromRawTheme(ThemeReader.readThemeSync("theme.json", new ByteArrayInputStream(theme.getBytes())), null); + } +} diff --git a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeParsingTest.java b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeParsingTest.java new file mode 100644 index 000000000..12c364ad3 --- /dev/null +++ b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeParsingTest.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.ByteArrayInputStream; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.tm4e.core.internal.theme.reader.ThemeReader; +import org.junit.jupiter.api.Test; + +/** + * + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/tests/themes.test.ts + * + */ +public class ThemeParsingTest { + + @Test + public void testCanParse() throws Exception { + final var actual = parseTheme(("{'settings': [" + + "{ 'settings': { 'foreground': '#F8F8F2', 'background': '#272822' } }," + + "{ 'scope': 'source, something', 'settings': { 'background': '#100000' } }," + + "{ 'scope': ['bar', 'baz'], 'settings': { 'background': '#010000' } }," + + "{ 'scope': 'source.css selector bar', 'settings': { 'fontStyle': 'bold' } }," + + "{ 'scope': 'constant', 'settings': { 'fontStyle': 'italic', 'foreground': '#ff0000' } }," + + "{ 'scope': 'constant.numeric', 'settings': { 'foreground': '#00ff00' } }," + + "{ 'scope': 'constant.numeric.hex', 'settings': { 'fontStyle': 'bold' } }," + + "{ 'scope': 'constant.numeric.oct', 'settings': { 'fontStyle': 'bold italic underline' } }," + + "{ 'scope': 'constant.numeric.bin', 'settings': { 'fontStyle': 'bold strikethrough' } }," + + "{ 'scope': 'constant.numeric.dec', 'settings': { 'fontStyle': '', 'foreground': '#0000ff' } }," + + "{ 'scope': 'foo', 'settings': { 'fontStyle': '', 'foreground': '#CFA' } }" + + "]}").replace('\'', '"')); + + final var expected = new ParsedThemeRule[] { + new ParsedThemeRule("", null, 0, FontStyle.NotSet, "#F8F8F2", "#272822"), + new ParsedThemeRule("source", null, 1, FontStyle.NotSet, null, "#100000"), + new ParsedThemeRule("something", null, 1, FontStyle.NotSet, null, "#100000"), + new ParsedThemeRule("bar", null, 2, FontStyle.NotSet, null, "#010000"), + new ParsedThemeRule("baz", null, 2, FontStyle.NotSet, null, "#010000"), + new ParsedThemeRule("bar", Arrays.asList("selector", "source.css"), 3, FontStyle.Bold, null, null), + new ParsedThemeRule("constant", null, 4, FontStyle.Italic, "#ff0000", null), + new ParsedThemeRule("constant.numeric", null, 5, FontStyle.NotSet, "#00ff00", null), + new ParsedThemeRule("constant.numeric.hex", null, 6, FontStyle.Bold, null, null), + new ParsedThemeRule("constant.numeric.oct", null, 7, + FontStyle.Bold | FontStyle.Italic | FontStyle.Underline, null, null), + new ParsedThemeRule("constant.numeric.bin", null, 8, FontStyle.Bold | FontStyle.Strikethrough, null, + null), + new ParsedThemeRule("constant.numeric.dec", null, 9, FontStyle.None, "#0000ff", null), + new ParsedThemeRule("foo", null, 10, FontStyle.None, "#CFA", null), }; + + assertArrayEquals(expected, actual.toArray()); + } + + private List parseTheme(String theme) throws Exception { + return Theme.parseTheme(ThemeReader.readThemeSync("theme.json", new ByteArrayInputStream(theme.getBytes()))); + } +} diff --git a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeResolvingTest.java b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeResolvingTest.java new file mode 100644 index 000000000..d24d57fb8 --- /dev/null +++ b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeResolvingTest.java @@ -0,0 +1,433 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.ByteArrayInputStream; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +import org.eclipse.tm4e.core.internal.theme.reader.ThemeReader; +import org.eclipse.tm4e.core.internal.utils.CompareUtils; +import org.junit.jupiter.api.Test; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/tests/themes.test.ts + */ +public class ThemeResolvingTest { + + private static final int NOT_SET = 0; + private static final ThemeTrieElementRule NOTSET_THEME_TRIE_ELEMENT_RULE = new ThemeTrieElementRule(0, null, + FontStyle.NotSet, NOT_SET, NOT_SET); + private static final ThemeTrieElement NOTSET_THEME_TRIE_ELEMENT = new ThemeTrieElement( + NOTSET_THEME_TRIE_ELEMENT_RULE); + + private static void assertStrArrCmp(String testCase, List a, List b, int expected) { + assertEquals(expected, CompareUtils.strArrCmp(a, b), testCase); + } + + private static Theme createTheme(ParsedThemeRule... rules) { + return Theme.createFromParsedTheme(List.of(rules), null); + } + + private static List parseTheme(String theme) throws Exception { + return Theme.parseTheme(ThemeReader.readThemeSync("theme.json", new ByteArrayInputStream(theme.getBytes()))); + } + + @Test + public void testThemeParsingCanParse() throws Exception { + var actual = parseTheme(("{" + + "'settings': [" + + "{ 'settings': { 'foreground': '#F8F8F2', 'background': '#272822' } }," + + "{ 'scope': 'source, something', 'settings': { 'background': '#100000' } }," + + "{ 'scope': ['bar', 'baz'], 'settings': { 'background': '#010000' } }," + + "{ 'scope': 'source.css selector bar', 'settings': { 'fontStyle': 'bold' } }," + + "{ 'scope': 'constant', 'settings': { 'fontStyle': 'italic', 'foreground': '#ff0000' } }," + + "{ 'scope': 'constant.numeric', 'settings': { 'foreground': '#00ff00' } }," + + "{ 'scope': 'constant.numeric.hex', 'settings': { 'fontStyle': 'bold' } }," + + "{ 'scope': 'constant.numeric.oct', 'settings': { 'fontStyle': 'bold italic underline' } }," + + "{ 'scope': 'constant.numeric.bin', 'settings': { 'fontStyle': 'bold strikethrough' } }," + + "{ 'scope': 'constant.numeric.dec', 'settings': { 'fontStyle': '', 'foreground': '#0000ff' } }," + + "{ 'scope': 'foo', 'settings': { 'fontStyle': '', 'foreground': '#CFA' } }" + + "]" + + "}").replace('\'', '"')); + + var expected = List.of( + new ParsedThemeRule("", null, 0, FontStyle.NotSet, "#F8F8F2", "#272822"), + new ParsedThemeRule("source", null, 1, FontStyle.NotSet, null, "#100000"), + new ParsedThemeRule("something", null, 1, FontStyle.NotSet, null, "#100000"), + new ParsedThemeRule("bar", null, 2, FontStyle.NotSet, null, "#010000"), + new ParsedThemeRule("baz", null, 2, FontStyle.NotSet, null, "#010000"), + new ParsedThemeRule("bar", List.of("selector", "source.css"), 3, FontStyle.Bold, null, null), + new ParsedThemeRule("constant", null, 4, FontStyle.Italic, "#ff0000", null), + new ParsedThemeRule("constant.numeric", null, 5, FontStyle.NotSet, "#00ff00", null), + new ParsedThemeRule("constant.numeric.hex", null, 6, FontStyle.Bold, null, null), + new ParsedThemeRule("constant.numeric.oct", null, 7, + FontStyle.Bold | FontStyle.Italic | FontStyle.Underline, null, null), + new ParsedThemeRule("constant.numeric.bin", null, 8, FontStyle.Bold | FontStyle.Strikethrough, null, + null), + new ParsedThemeRule("constant.numeric.dec", null, 9, FontStyle.None, "#0000ff", null), + new ParsedThemeRule("foo", null, 10, FontStyle.None, "#CFA", null)); + + assertArrayEquals(expected.toArray(), actual.toArray()); + } + + @Test + public void testStrcmpWorks() { + var actual = Arrays.asList("bar", "z", "zu", "a", "ab", ""); + actual.sort(CompareUtils::strcmp); + + var expected = List.of("", "a", "ab", "bar", "z", "zu"); + assertArrayEquals(expected.toArray(), actual.toArray()); + } + + @Test + public void testStrArrCmpWorks() { + assertStrArrCmp("001", null, null, 0); + assertStrArrCmp("002", null, Collections.emptyList(), -1); + assertStrArrCmp("003", null, List.of("a"), -1); + assertStrArrCmp("004", Collections.emptyList(), null, 1); + assertStrArrCmp("005", List.of("a"), null, 1); + assertStrArrCmp("006", Collections.emptyList(), Collections.emptyList(), 0); + assertStrArrCmp("007", Collections.emptyList(), List.of("a"), -1); + assertStrArrCmp("008", List.of("a"), Collections.emptyList(), 1); + assertStrArrCmp("009", List.of("a"), List.of("a"), 0); + assertStrArrCmp("010", List.of("a", "b"), List.of("a"), 1); + assertStrArrCmp("011", List.of("a"), List.of("a", "b"), -1); + assertStrArrCmp("012", List.of("a", "b"), List.of("a", "b"), 0); + assertStrArrCmp("013", List.of("a", "b"), List.of("a", "c"), -1); + assertStrArrCmp("014", List.of("a", "c"), List.of("a", "b"), 1); + } + + @Test + public void testAlwaysHasDefaults() { + var actual = createTheme(); + var colorMap = new ColorMap(); + int _A = colorMap.getId("#000000"); + int _B = colorMap.getId("#ffffff"); + var expected = new Theme(colorMap, + new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), NOTSET_THEME_TRIE_ELEMENT); + assertEquals(actual, expected); + } + + @Test + public void testRespectsIncomingDefaults1() { + var actual = createTheme(new ParsedThemeRule("", null, -1, FontStyle.NotSet, null, null)); + var colorMap = new ColorMap(); + int _A = colorMap.getId("#000000"); + int _B = colorMap.getId("#ffffff"); + var expected = new Theme(colorMap, + new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), NOTSET_THEME_TRIE_ELEMENT); + assertEquals(actual, expected); + } + + @Test + public void testRespectsIncomingDefaults2() { + Theme actual = createTheme(new ParsedThemeRule("", null, -1, FontStyle.None, null, null)); + var colorMap = new ColorMap(); + int _A = colorMap.getId("#000000"); + int _B = colorMap.getId("#ffffff"); + Theme expected = new Theme(colorMap, + new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), NOTSET_THEME_TRIE_ELEMENT); + assertEquals(actual, expected); + } + + @Test + public void testRespectsIncomingDefaults3() { + var actual = createTheme(new ParsedThemeRule("", null, -1, FontStyle.Bold, null, null)); + var colorMap = new ColorMap(); + int _A = colorMap.getId("#000000"); + int _B = colorMap.getId("#ffffff"); + var expected = new Theme(colorMap, + new ThemeTrieElementRule(0, null, FontStyle.Bold, _A, _B), NOTSET_THEME_TRIE_ELEMENT); + assertEquals(actual, expected); + } + + @Test + public void testRespectsIncomingDefaults4() { + var actual = createTheme(new ParsedThemeRule("", null, -1, FontStyle.NotSet, "#ff0000", null)); + var colorMap = new ColorMap(); + int _A = colorMap.getId("#ff0000"); + int _B = colorMap.getId("#ffffff"); + var expected = new Theme(colorMap, new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), + NOTSET_THEME_TRIE_ELEMENT); + assertEquals(actual, expected); + } + + @Test + public void testRespectsIncomingDefaults5() { + var actual = createTheme( + new ParsedThemeRule("", null, -1, FontStyle.NotSet, null, "#ff0000"), + new ParsedThemeRule("", null, -1, FontStyle.NotSet, "#00ff00", null), + new ParsedThemeRule("", null, -1, FontStyle.Bold, null, null)); + var colorMap = new ColorMap(); + int _A = colorMap.getId("#00ff00"); + int _B = colorMap.getId("#ff0000"); + var expected = new Theme(colorMap, new ThemeTrieElementRule(0, null, FontStyle.Bold, _A, _B), + NOTSET_THEME_TRIE_ELEMENT); + assertEquals(actual, expected); + } + + @Test + public void testCanMergeIncomingDefaults() { + var actual = createTheme( + new ParsedThemeRule("", null, -1, FontStyle.NotSet, null, "#ff0000"), + new ParsedThemeRule("", null, -1, FontStyle.NotSet, "#00ff00", null), + new ParsedThemeRule("", null, -1, FontStyle.Bold, null, null)); + var colorMap = new ColorMap(); + int _A = colorMap.getId("#00ff00"); + int _B = colorMap.getId("#ff0000"); + var expected = new Theme(colorMap, new ThemeTrieElementRule(0, null, FontStyle.Bold, _A, _B), + NOTSET_THEME_TRIE_ELEMENT); + assertEquals(actual, expected); + } + + @Test + public void testDefaultsAreInherited() { + Theme actual = createTheme( + new ParsedThemeRule("", null, -1, FontStyle.NotSet, "#F8F8F2", "#272822"), + new ParsedThemeRule("var", null, -1, FontStyle.NotSet, "#ff0000", null)); + var colorMap = new ColorMap(); + int _A = colorMap.getId("#F8F8F2"); + int _B = colorMap.getId("#272822"); + int _C = colorMap.getId("#ff0000"); + + var map = new HashMap(); + map.put("var", new ThemeTrieElement(new ThemeTrieElementRule(1, null, FontStyle.NotSet, _C, NOT_SET))); + + Theme expected = new Theme(colorMap, + new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), + new ThemeTrieElement(NOTSET_THEME_TRIE_ELEMENT_RULE, Collections.emptyList(), map)); + assertEquals(actual, expected); + } + + @Test + public void testSameRulesGetMerged() { + var actual = createTheme( + new ParsedThemeRule("", null, -1, FontStyle.NotSet, "#F8F8F2", "#272822"), + new ParsedThemeRule("var", null, 1, FontStyle.Bold, null, null), + new ParsedThemeRule("var", null, 0, FontStyle.NotSet, "#ff0000", null)); + var colorMap = new ColorMap(); + int _A = colorMap.getId("#F8F8F2"); + int _B = colorMap.getId("#272822"); + int _C = colorMap.getId("#ff0000"); + + var map = new HashMap(); + map.put("var", new ThemeTrieElement(new ThemeTrieElementRule(1, null, FontStyle.Bold, _C, NOT_SET))); + + var expected = new Theme(colorMap, + new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), + new ThemeTrieElement(NOTSET_THEME_TRIE_ELEMENT_RULE, Collections.emptyList(), map)); + assertEquals(actual, expected); + } + + @Test + public void testRulesAreInherited1() { + var actual = createTheme( + new ParsedThemeRule("", null, -1, FontStyle.NotSet, "#F8F8F2", "#272822"), + new ParsedThemeRule("var", null, -1, FontStyle.Bold, "#ff0000", null), + new ParsedThemeRule("var.identifier", null, -1, FontStyle.NotSet, "#00ff00", null)); + var colorMap = new ColorMap(); + int _A = colorMap.getId("#F8F8F2"); + int _B = colorMap.getId("#272822"); + int _C = colorMap.getId("#ff0000"); + int _D = colorMap.getId("#00ff00"); + + var map1_1 = new HashMap(); + map1_1.put("identifier", new ThemeTrieElement(new ThemeTrieElementRule(2, null, FontStyle.Bold, _D, NOT_SET))); + var map1 = new HashMap(); + map1.put("var", new ThemeTrieElement(new ThemeTrieElementRule(1, null, FontStyle.Bold, _C, NOT_SET), + Collections.emptyList(), map1_1)); + + var expected = new Theme(colorMap, + new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), + new ThemeTrieElement(NOTSET_THEME_TRIE_ELEMENT_RULE, Collections.emptyList(), map1)); + assertEquals(actual, expected); + } + + @Test + public void testRulesAreInherited2() { + var actual = createTheme( + new ParsedThemeRule("", null, -1, FontStyle.NotSet, "#F8F8F2", "#272822"), + new ParsedThemeRule("var", null, -1, FontStyle.Bold, "#ff0000", null), + new ParsedThemeRule("var.identifier", null, -1, FontStyle.NotSet, "#00ff00", null), + new ParsedThemeRule("constant", null, 4, FontStyle.Italic, "#100000", null), + new ParsedThemeRule("constant.numeric", null, 5, FontStyle.NotSet, "#200000", null), + new ParsedThemeRule("constant.numeric.hex", null, 6, FontStyle.Bold, null, null), + new ParsedThemeRule("constant.numeric.oct", null, 7, + FontStyle.Bold | FontStyle.Italic | FontStyle.Underline, null, null), + new ParsedThemeRule("constant.numeric.dec", null, 8, FontStyle.None, "#300000", null)); + var colorMap = new ColorMap(); + int _A = colorMap.getId("#F8F8F2"); + int _B = colorMap.getId("#272822"); + int _C = colorMap.getId("#100000"); + int _D = colorMap.getId("#200000"); + int _E = colorMap.getId("#300000"); + int _F = colorMap.getId("#ff0000"); + int _G = colorMap.getId("#00ff00"); + + var mapOfVar = new HashMap(); + mapOfVar.put("identifier", + new ThemeTrieElement(new ThemeTrieElementRule(2, null, FontStyle.Bold, _G, NOT_SET))); + + var mapOfNumeric = new HashMap(); + mapOfNumeric.put("hex", new ThemeTrieElement(new ThemeTrieElementRule(3, null, FontStyle.Bold, _D, NOT_SET))); + mapOfNumeric.put("oct", new ThemeTrieElement(new ThemeTrieElementRule(3, null, + FontStyle.Bold | FontStyle.Italic | FontStyle.Underline, _D, NOT_SET))); + mapOfNumeric.put("dec", new ThemeTrieElement(new ThemeTrieElementRule(3, null, FontStyle.None, _E, NOT_SET))); + + var mapOfConstant = new HashMap(); + mapOfConstant.put("numeric", new ThemeTrieElement(new ThemeTrieElementRule(2, null, + FontStyle.Italic, _D, NOT_SET), Collections.emptyList(), mapOfNumeric)); + + var mapRoot = new HashMap(); + mapRoot.put("var", new ThemeTrieElement(new ThemeTrieElementRule(1, null, + FontStyle.Bold, _F, NOT_SET), Collections.emptyList(), mapOfVar)); + mapRoot.put("constant", new ThemeTrieElement(new ThemeTrieElementRule(1, null, + FontStyle.Italic, _C, NOT_SET), Collections.emptyList(), mapOfConstant)); + + var expected = new Theme(colorMap, + new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), + new ThemeTrieElement(NOTSET_THEME_TRIE_ELEMENT_RULE, Collections.emptyList(), mapRoot)); + assertEquals(actual, expected); + } + + @Test + public void testRulesWithParentScopes() { + var actual = createTheme( + new ParsedThemeRule("", null, -1, FontStyle.NotSet, "#F8F8F2", "#272822"), + new ParsedThemeRule("var", null, -1, FontStyle.Bold, "#100000", null), + new ParsedThemeRule("var.identifier", null, -1, FontStyle.NotSet, "#200000", null), + new ParsedThemeRule("var", List.of("source.css"), 1, FontStyle.Italic, "#300000", null), + new ParsedThemeRule("var", List.of("source.css"), 2, FontStyle.Underline, null, null)); + var colorMap = new ColorMap(); + int _A = colorMap.getId("#F8F8F2"); + int _B = colorMap.getId("#272822"); + int _C = colorMap.getId("#100000"); + int _D = colorMap.getId("#300000"); + int _E = colorMap.getId("#200000"); + + var mapOfVar = new HashMap(); + mapOfVar.put("identifier", + new ThemeTrieElement(new ThemeTrieElementRule(2, null, FontStyle.Bold, _E, NOT_SET), List.of( + new ThemeTrieElementRule(1, List.of("source.css"), FontStyle.Underline, _D, NOT_SET)))); + + var mapRoot = new HashMap(); + mapRoot.put("var", + new ThemeTrieElement(new ThemeTrieElementRule(1, null, FontStyle.Bold, _C, NOT_SET), List.of( + new ThemeTrieElementRule(1, List.of("source.css"), FontStyle.Underline, _D, NOT_SET)), + mapOfVar)); + + var expected = new Theme(colorMap, + new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), + new ThemeTrieElement(NOTSET_THEME_TRIE_ELEMENT_RULE, Collections.emptyList(), mapRoot)); + assertEquals(actual, expected); + } + + @Test + public void testIssue_38_ignores_rules_with_invalid_colors() throws Exception { + var actual = parseTheme(("{" + + "'settings': [{" + + " 'settings': {" + + " 'background': '#222222'," + + " 'foreground': '#cccccc'" + + " }" + + "}, {" + + " 'name': 'Variable'," + + " 'scope': 'variable'," + + " 'settings': {" + + " 'fontStyle': ''" + + " }" + + "}, {" + + " 'name': 'Function argument'," + + " 'scope': 'variable.parameter'," + + " 'settings': {" + + " 'fontStyle': 'italic'," + + " 'foreground': ''" + + " }" + + "}, {" + + " 'name': 'Library variable'," + + " 'scope': 'support.other.variable'," + + " 'settings': {" + + " 'fontStyle': ''" + + " }" + + "}, {" + + " 'name': 'Function argument'," + + " 'scope': 'variable.other'," + + " 'settings': {" + + " 'foreground': ''," + + " 'fontStyle': 'normal'" + + " }" + + "}, {" + + " 'name': 'Coffeescript Function argument'," + + " 'scope': 'variable.parameter.function.coffee'," + + " 'settings': {" + + " 'foreground': '#F9D423'," + + " 'fontStyle': 'italic'" + + " }" + + "}]" + + "}").replace('\'', '"')); + + var expected = List.of( + new ParsedThemeRule("", null, 0, FontStyle.NotSet, "#cccccc", "#222222"), + new ParsedThemeRule("variable", null, 1, FontStyle.None, null, null), + new ParsedThemeRule("variable.parameter", null, 2, FontStyle.Italic, null, null), + new ParsedThemeRule("support.other.variable", null, 3, FontStyle.None, null, null), + new ParsedThemeRule("variable.other", null, 4, FontStyle.None, null, null), + new ParsedThemeRule("variable.parameter.function.coffee", null, 5, FontStyle.Italic, "#F9D423", null)); + + assertArrayEquals(expected.toArray(), actual.toArray()); + } + + @Test + public void testIssue_35_Trailing_comma_in_a_tmTheme_scope_selector() throws Exception { + var actual = parseTheme(("{" + + "'settings': [{" + + " 'settings': {" + + " 'background': '#25292C'," + + " 'foreground': '#EFEFEF'" + + " }" + + "}, {" + + " 'name': 'CSS at-rule keyword control'," + + " 'scope': '" + + " meta.at-rule.return.scss,\n" + + " meta.at-rule.return.scss punctuation.definition,\n" + + " meta.at-rule.else.scss,\n" + + " meta.at-rule.else.scss punctuation.definition,\n" + + " meta.at-rule.if.scss,\n" + + " meta.at-rule.if.scss punctuation.definition\n" + + " '," + + " 'settings': {" + + " 'foreground': '#CC7832'" + + " }" + + "}]" + + "}").replace('\'', '"')); + + var expected = List.of( + new ParsedThemeRule("", null, 0, FontStyle.NotSet, "#EFEFEF", "#25292C"), + new ParsedThemeRule("meta.at-rule.return.scss", null, 1, FontStyle.NotSet, "#CC7832", null), + new ParsedThemeRule("punctuation.definition", List.of("meta.at-rule.return.scss"), 1, + FontStyle.NotSet, "#CC7832", null), + new ParsedThemeRule("meta.at-rule.else.scss", null, 1, FontStyle.NotSet, "#CC7832", null), + new ParsedThemeRule("punctuation.definition", List.of("meta.at-rule.else.scss"), 1, + FontStyle.NotSet, "#CC7832", null), + new ParsedThemeRule("meta.at-rule.if.scss", null, 1, FontStyle.NotSet, "#CC7832", null), + new ParsedThemeRule("punctuation.definition", List.of("meta.at-rule.if.scss"), 1, + FontStyle.NotSet, "#CC7832", null)); + + assertArrayEquals(expected.toArray(), actual.toArray()); + } +} diff --git a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/theme/ThemeParsingTest.java b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/theme/ThemeParsingTest.java deleted file mode 100644 index 574232682..000000000 --- a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/theme/ThemeParsingTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.theme; - -import static org.junit.jupiter.api.Assertions.assertArrayEquals; - -import java.io.ByteArrayInputStream; -import java.util.Arrays; -import java.util.List; - -import org.eclipse.tm4e.core.internal.theme.reader.ThemeReader; -import org.junit.jupiter.api.Test; - -/** - * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/tests/themes.test.ts - * - */ -public class ThemeParsingTest { - - @Test - public void testCanParse() throws Exception { - List actual = parseTheme("{" + - "\"settings\": [" + - "{ \"settings\": { \"foreground\": \"#F8F8F2\", \"background\": \"#272822\" } }," + - "{ \"scope\": \"source, something\", \"settings\": { \"background\": \"#100000\" } }," + - "{ \"scope\": [\"bar\", \"baz\"], \"settings\": { \"background\": \"#010000\" } }," + - "{ \"scope\": \"source.css selector bar\", \"settings\": { \"fontStyle\": \"bold\" } }," + - "{ \"scope\": \"constant\", \"settings\": { \"fontStyle\": \"italic\", \"foreground\": \"#ff0000\" } }," + - "{ \"scope\": \"constant.numeric\", \"settings\": { \"foreground\": \"#00ff00\" } }," + - "{ \"scope\": \"constant.numeric.hex\", \"settings\": { \"fontStyle\": \"bold\" } }," + - "{ \"scope\": \"constant.numeric.oct\", \"settings\": { \"fontStyle\": \"bold italic underline\" } }," + - "{ \"scope\": \"constant.numeric.dec\", \"settings\": { \"fontStyle\": \"\", \"foreground\": \"#0000ff\" } }," + - "{ \"scope\": \"foo\", \"settings\": { \"fontStyle\": \"\", \"foreground\": \"#CFA\" } }" + - "]" + - "}"); - - - ParsedThemeRule[] expected = new ParsedThemeRule[] { - new ParsedThemeRule("", null, 0, FontStyle.NotSet, "#F8F8F2", "#272822"), - new ParsedThemeRule("source", null, 1, FontStyle.NotSet, null, "#100000"), - new ParsedThemeRule("something", null, 1, FontStyle.NotSet, null, "#100000"), - new ParsedThemeRule("bar", null, 2, FontStyle.NotSet, null, "#010000"), - new ParsedThemeRule("baz", null, 2, FontStyle.NotSet, null, "#010000"), - new ParsedThemeRule("bar", Arrays.asList("selector", "source.css"), 3, FontStyle.Bold, null, null), - new ParsedThemeRule("constant", null, 4, FontStyle.Italic, "#ff0000", null), - new ParsedThemeRule("constant.numeric", null, 5, FontStyle.NotSet, "#00ff00", null), - new ParsedThemeRule("constant.numeric.hex", null, 6, FontStyle.Bold, null, null), - new ParsedThemeRule("constant.numeric.oct", null, 7, - FontStyle.Bold | FontStyle.Italic | FontStyle.Underline, null, null), - new ParsedThemeRule("constant.numeric.dec", null, 8, FontStyle.None, "#0000ff", null), - new ParsedThemeRule("foo", null, 9, FontStyle.None, "#CFA", null), }; - - assertArrayEquals(expected, actual.toArray()); - } - - private List parseTheme(String theme) throws Exception { - return Theme.parseTheme(ThemeReader.JSON_PARSER.parse(new ByteArrayInputStream(theme.getBytes()))); - } -} diff --git a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/theme/ThemeResolvingTest.java b/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/theme/ThemeResolvingTest.java deleted file mode 100644 index cd1a51ebc..000000000 --- a/org.eclipse.tm4e.core.tests/src/main/java/org/eclipse/tm4e/core/theme/ThemeResolvingTest.java +++ /dev/null @@ -1,405 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.theme; - -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.ByteArrayInputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.eclipse.tm4e.core.internal.theme.reader.ThemeReader; -import org.eclipse.tm4e.core.internal.utils.CompareUtils; -import org.junit.jupiter.api.Test; - -/** - * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/tests/themes.test.ts - * - */ -public class ThemeResolvingTest { - - @Test - public void testStrcmpWorks() { - List actual = Arrays.asList("bar", "z", "zu", "a", "ab", ""); - actual.sort(CompareUtils::strcmp); - - List expected = Arrays.asList("", "a", "ab", "bar", "z", "zu"); - assertArrayEquals(expected.toArray(), actual.toArray()); - } - - @Test - public void testStrArrCmpWorks() { - assertStrArrCmp("001", null, null, 0); - assertStrArrCmp("002", null, Collections.emptyList(), -1); - assertStrArrCmp("003", null, Arrays.asList("a"), -1); - assertStrArrCmp("004", Collections.emptyList(), null, 1); - assertStrArrCmp("005", Arrays.asList("a"), null, 1); - assertStrArrCmp("006", Collections.emptyList(), Collections.emptyList(), 0); - assertStrArrCmp("007", Collections.emptyList(), Arrays.asList("a"), -1); - assertStrArrCmp("008", Arrays.asList("a"), Collections.emptyList(), 1); - assertStrArrCmp("009", Arrays.asList("a"), Arrays.asList("a"), 0); - assertStrArrCmp("010", Arrays.asList("a", "b"), Arrays.asList("a"), 1); - assertStrArrCmp("011", Arrays.asList("a"), Arrays.asList("a", "b"), -1); - assertStrArrCmp("012", Arrays.asList("a", "b"), Arrays.asList("a", "b"), 0); - assertStrArrCmp("013", Arrays.asList("a", "b"), Arrays.asList("a", "c"), -1); - assertStrArrCmp("014", Arrays.asList("a", "c"), Arrays.asList("a", "b"), 1); - } - - @Test - public void testAlwaysHasDefaults() { - Theme actual = Theme.createFromParsedTheme(Collections.emptyList()); - ColorMap colorMap = new ColorMap(); - int _NOT_SET = 0; - int _A = colorMap.getId("#000000"); - int _B = colorMap.getId("#ffffff"); - Theme expected = new Theme(colorMap, new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), - new ThemeTrieElement(new ThemeTrieElementRule(0, null, FontStyle.NotSet, _NOT_SET, _NOT_SET))); - assertEquals(actual, expected); - } - - @Test - public void testRespectsIncomingDefaults1() { - Theme actual = Theme.createFromParsedTheme( - new ArrayList<>(Arrays.asList(new ParsedThemeRule("", null, -1, FontStyle.NotSet, null, null)))); - ColorMap colorMap = new ColorMap(); - int _NOT_SET = 0; - int _A = colorMap.getId("#000000"); - int _B = colorMap.getId("#ffffff"); - Theme expected = new Theme(colorMap, new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), - new ThemeTrieElement(new ThemeTrieElementRule(0, null, FontStyle.NotSet, _NOT_SET, _NOT_SET))); - assertEquals(actual, expected); - } - - @Test - public void testRespectsIncomingDefaults2() { - Theme actual = Theme.createFromParsedTheme( - new ArrayList<>(Arrays.asList(new ParsedThemeRule("", null, -1, FontStyle.None, null, null)))); - ColorMap colorMap = new ColorMap(); - int _NOT_SET = 0; - int _A = colorMap.getId("#000000"); - int _B = colorMap.getId("#ffffff"); - Theme expected = new Theme(colorMap, new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), - new ThemeTrieElement(new ThemeTrieElementRule(0, null, FontStyle.NotSet, _NOT_SET, _NOT_SET))); - assertEquals(actual, expected); - } - - @Test - public void testRespectsIncomingDefaults3() { - Theme actual = Theme.createFromParsedTheme( - new ArrayList<>(Arrays.asList(new ParsedThemeRule("", null, -1, FontStyle.Bold, null, null)))); - ColorMap colorMap = new ColorMap(); - int _NOT_SET = 0; - int _A = colorMap.getId("#000000"); - int _B = colorMap.getId("#ffffff"); - Theme expected = new Theme(colorMap, new ThemeTrieElementRule(0, null, FontStyle.Bold, _A, _B), - new ThemeTrieElement(new ThemeTrieElementRule(0, null, FontStyle.NotSet, _NOT_SET, _NOT_SET))); - assertEquals(actual, expected); - } - - @Test - public void testRespectsIncomingDefaults4() { - Theme actual = Theme.createFromParsedTheme( - new ArrayList<>(Arrays.asList(new ParsedThemeRule("", null, -1, FontStyle.NotSet, "#ff0000", null)))); - ColorMap colorMap = new ColorMap(); - int _NOT_SET = 0; - int _A = colorMap.getId("#ff0000"); - int _B = colorMap.getId("#ffffff"); - Theme expected = new Theme(colorMap, new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), - new ThemeTrieElement(new ThemeTrieElementRule(0, null, FontStyle.NotSet, _NOT_SET, _NOT_SET))); - assertEquals(actual, expected); - } - - @Test - public void testRespectsIncomingDefaults5() { - Theme actual = Theme.createFromParsedTheme( - new ArrayList<>(Arrays.asList(new ParsedThemeRule("", null, -1, FontStyle.NotSet, null, "#ff0000"), - new ParsedThemeRule("", null, -1, FontStyle.NotSet, "#00ff00", null), - new ParsedThemeRule("", null, -1, FontStyle.Bold, null, null)))); - ColorMap colorMap = new ColorMap(); - int _NOT_SET = 0; - int _A = colorMap.getId("#00ff00"); - int _B = colorMap.getId("#ff0000"); - Theme expected = new Theme(colorMap, new ThemeTrieElementRule(0, null, FontStyle.Bold, _A, _B), - new ThemeTrieElement(new ThemeTrieElementRule(0, null, FontStyle.NotSet, _NOT_SET, _NOT_SET))); - assertEquals(actual, expected); - } - - @Test - public void testCanMergeIncomingDefaults() { - Theme actual = Theme.createFromParsedTheme( - new ArrayList<>(Arrays.asList(new ParsedThemeRule("", null, -1, FontStyle.NotSet, null, "#ff0000"), - new ParsedThemeRule("", null, -1, FontStyle.NotSet, "#00ff00", null), - new ParsedThemeRule("", null, -1, FontStyle.Bold, null, null)))); - ColorMap colorMap = new ColorMap(); - int _NOT_SET = 0; - int _A = colorMap.getId("#00ff00"); - int _B = colorMap.getId("#ff0000"); - Theme expected = new Theme(colorMap, new ThemeTrieElementRule(0, null, FontStyle.Bold, _A, _B), - new ThemeTrieElement(new ThemeTrieElementRule(0, null, FontStyle.NotSet, _NOT_SET, _NOT_SET))); - assertEquals(actual, expected); - } - - @Test - public void testDefaultsAreInherited() { - Theme actual = Theme.createFromParsedTheme( - new ArrayList<>(Arrays.asList(new ParsedThemeRule("", null, -1, FontStyle.NotSet, "#F8F8F2", "#272822"), - new ParsedThemeRule("var", null, -1, FontStyle.NotSet, "#ff0000", null)))); - ColorMap colorMap = new ColorMap(); - int _NOT_SET = 0; - int _A = colorMap.getId("#F8F8F2"); - int _B = colorMap.getId("#272822"); - int _C = colorMap.getId("#ff0000"); - - Map map = new HashMap<>(); - map.put("var", new ThemeTrieElement(new ThemeTrieElementRule(1, null, FontStyle.NotSet, _C, _NOT_SET))); - - Theme expected = new Theme(colorMap, new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), - new ThemeTrieElement(new ThemeTrieElementRule(0, null, FontStyle.NotSet, _NOT_SET, _NOT_SET), - Collections.emptyList(), map)); - assertEquals(actual, expected); - } - - @Test - public void testSameRulesGetMerged() { - Theme actual = Theme.createFromParsedTheme( - new ArrayList<>(Arrays.asList(new ParsedThemeRule("", null, -1, FontStyle.NotSet, "#F8F8F2", "#272822"), - new ParsedThemeRule("var", null, 1, FontStyle.Bold, null, null), - new ParsedThemeRule("var", null, 0, FontStyle.NotSet, "#ff0000", null)))); - ColorMap colorMap = new ColorMap(); - int _NOT_SET = 0; - int _A = colorMap.getId("#F8F8F2"); - int _B = colorMap.getId("#272822"); - int _C = colorMap.getId("#ff0000"); - - Map map = new HashMap<>(); - map.put("var", new ThemeTrieElement(new ThemeTrieElementRule(1, null, FontStyle.Bold, _C, _NOT_SET))); - - Theme expected = new Theme(colorMap, new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), - new ThemeTrieElement(new ThemeTrieElementRule(0, null, FontStyle.NotSet, _NOT_SET, _NOT_SET), - Collections.emptyList(), map)); - assertEquals(actual, expected); - } - - @Test - public void testRulesAreInherited1() { - Theme actual = Theme.createFromParsedTheme( - new ArrayList<>(Arrays.asList(new ParsedThemeRule("", null, -1, FontStyle.NotSet, "#F8F8F2", "#272822"), - new ParsedThemeRule("var", null, -1, FontStyle.Bold, "#ff0000", null), - new ParsedThemeRule("var.identifier", null, -1, FontStyle.NotSet, "#00ff00", null)))); - ColorMap colorMap = new ColorMap(); - int _NOT_SET = 0; - int _A = colorMap.getId("#F8F8F2"); - int _B = colorMap.getId("#272822"); - int _C = colorMap.getId("#ff0000"); - int _D = colorMap.getId("#00ff00"); - - Map map1_1 = new HashMap<>(); - map1_1.put("identifier", new ThemeTrieElement(new ThemeTrieElementRule(2, null, FontStyle.Bold, _D, _NOT_SET))); - Map map1 = new HashMap<>(); - map1.put("var", new ThemeTrieElement(new ThemeTrieElementRule(1, null, FontStyle.Bold, _C, _NOT_SET), - Collections.emptyList(), map1_1)); - - Theme expected = new Theme(colorMap, new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), - new ThemeTrieElement(new ThemeTrieElementRule(0, null, FontStyle.NotSet, _NOT_SET, _NOT_SET), - Collections.emptyList(), map1)); - assertEquals(actual, expected); - } - - @Test - public void testRulesAreInherited2() { - Theme actual = Theme.createFromParsedTheme( - new ArrayList<>(Arrays.asList(new ParsedThemeRule("", null, -1, FontStyle.NotSet, "#F8F8F2", "#272822"), - new ParsedThemeRule("var", null, -1, FontStyle.Bold, "#ff0000", null), - new ParsedThemeRule("var.identifier", null, -1, FontStyle.NotSet, "#00ff00", null), - new ParsedThemeRule("constant", null, 4, FontStyle.Italic, "#100000", null), - new ParsedThemeRule("constant.numeric", null, 5, FontStyle.NotSet, "#200000", null), - new ParsedThemeRule("constant.numeric.hex", null, 6, FontStyle.Bold, null, null), - new ParsedThemeRule("constant.numeric.oct", null, 7, - FontStyle.Bold | FontStyle.Italic | FontStyle.Underline, null, null), - new ParsedThemeRule("constant.numeric.dec", null, 8, FontStyle.None, "#300000", null)))); - ColorMap colorMap = new ColorMap(); - int _NOT_SET = 0; - int _A = colorMap.getId("#F8F8F2"); - int _B = colorMap.getId("#272822"); - int _C = colorMap.getId("#100000"); - int _D = colorMap.getId("#200000"); - int _E = colorMap.getId("#300000"); - int _F = colorMap.getId("#ff0000"); - int _G = colorMap.getId("#00ff00"); - - Map mapOfVar = new HashMap<>(); - mapOfVar.put("identifier", - new ThemeTrieElement(new ThemeTrieElementRule(2, null, FontStyle.Bold, _G, _NOT_SET))); - - Map mapOfNumeric = new HashMap<>(); - mapOfNumeric.put("hex", new ThemeTrieElement(new ThemeTrieElementRule(3, null, FontStyle.Bold, _D, _NOT_SET))); - mapOfNumeric.put("oct", new ThemeTrieElement(new ThemeTrieElementRule(3, null, - FontStyle.Bold | FontStyle.Italic | FontStyle.Underline, _D, _NOT_SET))); - mapOfNumeric.put("dec", new ThemeTrieElement(new ThemeTrieElementRule(3, null, FontStyle.None, _E, _NOT_SET))); - - Map mapOfConstant = new HashMap<>(); - mapOfConstant.put("numeric", - new ThemeTrieElement(new ThemeTrieElementRule(2, null, FontStyle.Italic, _D, _NOT_SET), - Collections.emptyList(), mapOfNumeric)); - - Map mapRoot = new HashMap<>(); - mapRoot.put("var", new ThemeTrieElement(new ThemeTrieElementRule(1, null, FontStyle.Bold, _F, _NOT_SET), - Collections.emptyList(), mapOfVar)); - mapRoot.put("constant", new ThemeTrieElement(new ThemeTrieElementRule(1, null, FontStyle.Italic, _C, _NOT_SET), - Collections.emptyList(), mapOfConstant)); - - Theme expected = new Theme(colorMap, new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), - new ThemeTrieElement(new ThemeTrieElementRule(0, null, FontStyle.NotSet, _NOT_SET, _NOT_SET), - Collections.emptyList(), mapRoot)); - assertEquals(actual, expected); - } - - @Test - public void testRulesWithParentScopes() { - Theme actual = Theme.createFromParsedTheme( - new ArrayList<>(Arrays.asList(new ParsedThemeRule("", null, -1, FontStyle.NotSet, "#F8F8F2", "#272822"), - new ParsedThemeRule("var", null, -1, FontStyle.Bold, "#100000", null), - new ParsedThemeRule("var.identifier", null, -1, FontStyle.NotSet, "#200000", null), - new ParsedThemeRule("var", Arrays.asList("source.css"), 1, FontStyle.Italic, "#300000", null), - new ParsedThemeRule("var", Arrays.asList("source.css"), 2, FontStyle.Underline, null, null)))); - ColorMap colorMap = new ColorMap(); - int _NOT_SET = 0; - int _A = colorMap.getId("#F8F8F2"); - int _B = colorMap.getId("#272822"); - int _C = colorMap.getId("#100000"); - int _D = colorMap.getId("#300000"); - int _E = colorMap.getId("#200000"); - - Map mapOfVar = new HashMap<>(); - mapOfVar.put("identifier", - new ThemeTrieElement(new ThemeTrieElementRule(2, null, FontStyle.Bold, _E, _NOT_SET), Arrays.asList( - new ThemeTrieElementRule(1, Arrays.asList("source.css"), FontStyle.Underline, _D, _NOT_SET)))); - - Map mapRoot = new HashMap<>(); - mapRoot.put("var", - new ThemeTrieElement(new ThemeTrieElementRule(1, null, FontStyle.Bold, _C, _NOT_SET), Arrays.asList( - new ThemeTrieElementRule(1, Arrays.asList("source.css"), FontStyle.Underline, _D, _NOT_SET)), - mapOfVar)); - - Theme expected = new Theme(colorMap, new ThemeTrieElementRule(0, null, FontStyle.None, _A, _B), - new ThemeTrieElement(new ThemeTrieElementRule(0, null, FontStyle.NotSet, _NOT_SET, _NOT_SET), - Collections.emptyList(), mapRoot)); - assertEquals(actual, expected); - } - - @Test - public void testIssue_38_ignores_rules_with_invalid_colors() throws Exception { - List actual = parseTheme("{" + - "\"settings\": [{"+ - " \"settings\": {"+ - " \"background\": \"#222222\","+ - " \"foreground\": \"#cccccc\""+ - " }"+ - "}, {"+ - " \"name\": \"Variable\","+ - " \"scope\": \"variable\","+ - " \"settings\": {"+ - " \"fontStyle\": \"\""+ - " }"+ - "}, {"+ - " \"name\": \"Function argument\","+ - " \"scope\": \"variable.parameter\","+ - " \"settings\": {"+ - " \"fontStyle\": \"italic\","+ - " \"foreground\": \"\""+ - " }"+ - "}, {"+ - " \"name\": \"Library variable\","+ - " \"scope\": \"support.other.variable\","+ - " \"settings\": {"+ - " \"fontStyle\": \"\""+ - " }"+ - "}, {"+ - " \"name\": \"Function argument\","+ - " \"scope\": \"variable.other\","+ - " \"settings\": {"+ - " \"foreground\": \"\","+ - " \"fontStyle\": \"normal\""+ - " }"+ - "}, {"+ - " \"name\": \"Coffeescript Function argument\","+ - " \"scope\": \"variable.parameter.function.coffee\","+ - " \"settings\": {"+ - " \"foreground\": \"#F9D423\","+ - " \"fontStyle\": \"italic\""+ - " }"+ - "}]"+ - "}"); - - List expected = Arrays.asList( - new ParsedThemeRule("", null, 0, FontStyle.NotSet, "#cccccc", "#222222"), - new ParsedThemeRule("variable", null, 1, FontStyle.None, null, null), - new ParsedThemeRule("variable.parameter", null, 2, FontStyle.Italic, null, null), - new ParsedThemeRule("support.other.variable", null, 3, FontStyle.None, null, null), - new ParsedThemeRule("variable.other", null, 4, FontStyle.None, null, null), - new ParsedThemeRule("variable.parameter.function.coffee", null, 5, FontStyle.Italic, "#F9D423", null) - ); - - assertArrayEquals(expected.toArray(), actual.toArray()); - } - - @Test - public void testIssue_35_Trailing_comma_in_a_tmTheme_scope_selector() throws Exception { - List actual = parseTheme("{" + - "\"settings\": [{"+ - " \"settings\": {"+ - " \"background\": \"#25292C\","+ - " \"foreground\": \"#EFEFEF\""+ - " }"+ - "}, {"+ - " \"name\": \"CSS at-rule keyword control\","+ - " \"scope\": \""+ - " meta.at-rule.return.scss,\n"+ - " meta.at-rule.return.scss punctuation.definition,\n"+ - " meta.at-rule.else.scss,\n"+ - " meta.at-rule.else.scss punctuation.definition,\n"+ - " meta.at-rule.if.scss,\n"+ - " meta.at-rule.if.scss punctuation.definition\n"+ - " \","+ - " \"settings\": {"+ - " \"foreground\": \"#CC7832\""+ - " }"+ - "}]"+ - "}"); - - List expected = Arrays.asList( - new ParsedThemeRule("", null, 0, FontStyle.NotSet, "#EFEFEF", "#25292C"), - new ParsedThemeRule("meta.at-rule.return.scss", null, 1, FontStyle.NotSet, "#CC7832", null), - new ParsedThemeRule("punctuation.definition", Arrays.asList("meta.at-rule.return.scss"), 1, FontStyle.NotSet, "#CC7832", null), - new ParsedThemeRule("meta.at-rule.else.scss", null, 1, FontStyle.NotSet, "#CC7832", null), - new ParsedThemeRule("punctuation.definition", Arrays.asList("meta.at-rule.else.scss"), 1, FontStyle.NotSet, "#CC7832", null), - new ParsedThemeRule("meta.at-rule.if.scss", null, 1, FontStyle.NotSet, "#CC7832", null), - new ParsedThemeRule("punctuation.definition", Arrays.asList("meta.at-rule.if.scss"), 1, FontStyle.NotSet, "#CC7832", null) - ); - - assertArrayEquals(expected.toArray(), actual.toArray()); - } - - private void assertStrArrCmp(String testCase, List a, List b, int expected) { - assertEquals(expected, CompareUtils.strArrCmp(a, b), testCase); - } - - private List parseTheme(String theme) throws Exception { - return Theme.parseTheme(ThemeReader.JSON_PARSER.parse(new ByteArrayInputStream(theme.getBytes()))); - } -} diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/matcher-tests.json b/org.eclipse.tm4e.core.tests/src/main/resources/matcher-tests.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/matcher-tests.json rename to org.eclipse.tm4e.core.tests/src/main/resources/matcher-tests.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/README.md b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/README.md similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/README.md rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/README.md diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/apply-end-pattern-last.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/apply-end-pattern-last.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/apply-end-pattern-last.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/apply-end-pattern-last.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/c-plus-plus.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/c-plus-plus.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/c-plus-plus.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/c-plus-plus.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/c.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/c.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/c.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/c.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/coffee-script.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/coffee-script.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/coffee-script.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/coffee-script.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/content-name.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/content-name.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/content-name.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/content-name.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/css.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/css.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/css.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/css.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/forever.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/forever.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/forever.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/forever.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/git-commit.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/git-commit.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/git-commit.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/git-commit.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/hello.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/hello.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/hello.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/hello.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/html-erb.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/html-erb.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/html-erb.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/html-erb.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/html-rails.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/html-rails.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/html-rails.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/html-rails.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/html.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/html.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/html.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/html.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/hyperlink.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/hyperlink.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/hyperlink.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/hyperlink.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/imaginary.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/imaginary.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/imaginary.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/imaginary.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/include-external-repository-rule.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/include-external-repository-rule.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/include-external-repository-rule.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/include-external-repository-rule.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/infinite-loop.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/infinite-loop.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/infinite-loop.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/infinite-loop.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/java.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/java.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/java.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/java.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/javascript-regex.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/javascript-regex.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/javascript-regex.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/javascript-regex.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/javascript.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/javascript.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/javascript.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/javascript.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/json.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/json.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/json.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/json.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/latex.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/latex.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/latex.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/latex.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/loops.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/loops.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/loops.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/loops.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/makefile.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/makefile.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/makefile.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/makefile.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/multiline.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/multiline.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/multiline.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/multiline.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/nested-captures.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/nested-captures.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/nested-captures.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/nested-captures.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/objective-c-plus-plus.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/objective-c-plus-plus.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/objective-c-plus-plus.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/objective-c-plus-plus.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/objective-c.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/objective-c.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/objective-c.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/objective-c.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/php.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/php.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/php.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/php.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/python-regex.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/python-regex.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/python-regex.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/python-regex.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/python.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/python.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/python.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/python.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/ruby-on-rails.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/ruby-on-rails.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/ruby-on-rails.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/ruby-on-rails.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/ruby.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/ruby.json similarity index 99% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/ruby.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/ruby.json index 17e49e19c..dfc6c8cbb 100644 --- a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/ruby.json +++ b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/ruby.json @@ -219,7 +219,7 @@ "name": "variable.other.constant.ruby" }, { - "begin": "(?x)\n\t\t\t (?=def\\b) # an optimization to help Oniguruma fail fast\n\t\t\t (?<=^|\\s)(def)\\s+ # the def keyword\n\t\t\t ( (?>[a-zA-Z_]\\w*(?>\\.|::))? # a method name prefix\n\t\t\t (?>[a-zA-Z_]\\w*(?>[?!]|=(?!>))? # the method name\n\t\t\t |===?|>[>=]?|<=>|<[<=]?|[%&`/\\|]|\\*\\*?|=?~|[-+]@?|\\[\\]=?) ) # …or an operator method\n\t\t\t \\s*(\\() # the openning parenthesis for arguments\n\t\t\t ", + "begin": "(?x)\n\t\t\t (?=def\\b) # an optimization to help Oniguruma fail fast\n\t\t\t (?<=^|\\s)(def)\\s+ # the def keyword\n\t\t\t ( (?>[a-zA-Z_]\\w*(?>\\.|::))? # a method name prefix\n\t\t\t (?>[a-zA-Z_]\\w*(?>[?!]|=(?!>))? # the method name\n\t\t\t |===?|>[>=]?|<=>|<[<=]?|[%&`/\\|]|\\*\\*?|=?~|[-+]@?|\\[\\]=?) ) # …or an operator method\n\t\t\t \\s*(\\() # the opening parenthesis for arguments\n\t\t\t ", "beginCaptures": { "1": { "name": "keyword.control.def.ruby" diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/scss.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/scss.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/scss.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/scss.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/sql.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/sql.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/sql.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/sql.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/text.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/text.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/text.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/text.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/thrift.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/thrift.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/thrift.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/thrift.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/todo.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/todo.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/fixtures/todo.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/fixtures/todo.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/tests.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/tests.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/first-mate/tests.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/first-mate/tests.json diff --git a/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/105.grammarA.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/105.grammarA.json new file mode 100644 index 000000000..8d74b8c63 --- /dev/null +++ b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/105.grammarA.json @@ -0,0 +1,20 @@ +{ + "scopeName": "source.test", + "patterns": [{ "include": "#test" }, { "include": "#embedded" }], + "repository": { + "test": { + "begin": "testStart", + "end": "testEnd", + "patterns": [{ "include": "#test2" }] + }, + "test2": { + "match": "some test pattern", + "name": "test.name" + }, + "embedded": { + "begin": "embedStart", + "end": "embedEnd", + "patterns": [{ "include": "source.test.embedded" }] + } + } +} diff --git a/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/105.grammarB.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/105.grammarB.json new file mode 100644 index 000000000..d08bbf2d1 --- /dev/null +++ b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/105.grammarB.json @@ -0,0 +1,14 @@ +{ + "scopeName": "source.test.embedded", + "patterns": [{ "include": "#test" }], + "repository": { + "test": { + "begin": "testStart", + "end": "testEnd", + "patterns": [{ "include": "#test2" }] + }, + "test2": { + "include": "source.test#test2" + } + } +} diff --git a/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/147.grammar.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/147.grammar.json new file mode 100644 index 000000000..7f214d731 --- /dev/null +++ b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/147.grammar.json @@ -0,0 +1,9 @@ +{ + "scopeName": "source.test", + "patterns": [ + { + "match": "\\b(?i:function)\\b", + "name": "storage.type.$0 keyword.declaration.$0" + } + ] +} \ No newline at end of file diff --git a/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/66.plist b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/66.plist new file mode 100644 index 000000000..0e22924a4 --- /dev/null +++ b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/66.plist @@ -0,0 +1,21 @@ + + + + + scopeName + text.test + + patterns + + + begin^. + namecomment + + + + begin. + nameinvalid + + + + \ No newline at end of file diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/Jade.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Jade.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/Jade.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Jade.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/Jade.tmLanguage b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Jade.tmLanguage similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/Jade.tmLanguage rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Jade.tmLanguage diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Jade.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Jade22.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Jade.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Jade22.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/Makefile.plist b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Makefile.plist similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/Makefile.plist rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Makefile.plist diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/Markdown.tmLanguage b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Markdown.tmLanguage similarity index 96% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/Markdown.tmLanguage rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Markdown.tmLanguage index fa056f47a..9a5ca66b5 100644 --- a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/Markdown.tmLanguage +++ b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Markdown.tmLanguage @@ -1,1108 +1,1108 @@ - - - - - fileTypes - - md - mdown - markdown - markdn - - keyEquivalent - ^~M - name - Markdown - patterns - - - include - #block - - - repository - - block - - patterns - - - include - #separator - - - include - #heading - - - include - #blockquote - - - include - #lists - - - include - #raw_block - - - include - #link-def - - - include - #html - - - include - #paragraph - - - repository - - blockquote - - begin - (^|\G)(>) ? - captures - - 2 - - name - punctuation.definition.quote.markdown - - - name - markup.quote.markdown - patterns - - - include - #block - - - while - (^|\G)(>) ? - - heading - - begin - (?:^|\G)(#{1,6})\s*(?=[\S[^#]]) - captures - - 1 - - name - punctuation.definition.heading.markdown - - - contentName - entity.name.section.markdown - end - \s*(#{1,6})?$\n? - name - markup.heading.markdown - patterns - - - include - #inline - - - - heading-setext - - patterns - - - match - ^(={3,})(?=[ \t]*$\n?) - name - markup.heading.setext.1.markdown - - - match - ^(-{3,})(?=[ \t]*$\n?) - name - markup.heading.setext.2.markdown - - - - html - - patterns - - - begin - (?i)(^|\G)(?=<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del).*</\2\s*>\s*$) - end - $ - patterns - - - include - text.html.basic - - - - - begin - (?i)(^|\G)(?=<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)) - patterns - - - include - text.html.basic - - - while - \G(?!</\2\s*>) - - - - link-def - - captures - - 1 - - name - punctuation.definition.constant.markdown - - 10 - - name - punctuation.definition.string.end.markdown - - 11 - - name - string.other.link.description.title.markdown - - 12 - - name - punctuation.definition.string.begin.markdown - - 13 - - name - punctuation.definition.string.end.markdown - - 2 - - name - constant.other.reference.link.markdown - - 3 - - name - punctuation.definition.constant.markdown - - 4 - - name - punctuation.separator.key-value.markdown - - 5 - - name - punctuation.definition.link.markdown - - 6 - - name - markup.underline.link.markdown - - 7 - - name - punctuation.definition.link.markdown - - 8 - - name - string.other.link.description.title.markdown - - 9 - - name - punctuation.definition.string.begin.markdown - - - match - ^(?x: - \s* # Leading whitespace - (\[)(.+?)(\])(:) # Reference name - [ \t]* # Optional whitespace - (<?)(\S+?)(>?) # The url - [ \t]* # Optional whitespace - (?: - ((\().+?(\))) # Match title in quotes… - | ((").+?(")) # or in parens. - )? # Title is optional - \s* # Optional whitespace - $ - ) - name - meta.link.reference.def.markdown - - list_paragraph - - begin - (^|\G)(?=\S)(?![*+-]\s|[0-9]+\.\s) - name - meta.paragraph.markdown - patterns - - - include - #inline - - - include - text.html.basic - - - include - #heading-setext - - - while - (^|\G)(?!\s*$|#|[ ]{0,3}([-*_][ ]{2,}){3,}[ \t]*$\n?|>|[ ]{0,3}[*+-]|[ ]{0,3}[0-9]+\.) - - lists - - patterns - - - begin - (^|\G)([ ]{0,3})([*+-])([ ]{1,3}|\t) - beginCaptures - - 3 - - name - punctuation.definition.list.markdown - - - comment - Currently does not support un-indented second lines. - name - markup.list.unnumbered.markdown - patterns - - - include - #list_paragraph - - - include - #block - - - while - \G([ ]{4}|\t|$) - - - begin - (^|\G)([ ]{0,3})([0-9]+\.)([ ]{1,3}|\t) - beginCaptures - - 3 - - name - punctuation.definition.list.markdown - - - name - markup.list.numbered.markdown - patterns - - - include - #list_paragraph - - - include - #block - - - while - \G([ ]{4}|\t|$) - - - - paragraph - - begin - (^|\G)(?=\S) - name - meta.paragraph.markdown - patterns - - - include - #inline - - - include - text.html.basic - - - include - #heading-setext - - - while - (^|\G)(?!\s*$|#|[ ]{0,3}([-*_][ ]{2,}){3,}[ \t]*$\n?|\s*\[.+?\]:|>) - - raw_block - - begin - (^|\G)([ ]{4}|\t) - name - markup.raw.block.markdown - while - (^|\G)([ ]{4}|\t) - - separator - - match - (^|\G)[ ]{0,3}([-*_])([ ]{0,2}\2){2,}[ \t]*$\n? - name - meta.separator.markdown - - - - inline - - patterns - - - include - #ampersand - - - include - #bracket - - - include - #bold - - - include - #italic - - - include - #raw - - - include - #escape - - - include - #image-inline - - - include - #image-ref - - - include - #link-email - - - include - #link-inet - - - include - #link-inline - - - include - #link-ref - - - include - #link-ref-literal - - - repository - - ampersand - - comment - - Markdown will convert this for us. We match it so that the - HTML grammar will not mark it up as invalid. - - match - &(?!([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+);) - name - meta.other.valid-ampersand.markdown - - bold - - begin - (?x) - (\*\*|__)(?=\S) # Open - (?= - ( - <[^>]*+> # HTML tags - | (?<raw>`+)([^`]|(?!(?<!`)\k<raw>(?!`))`)*+\k<raw> - # Raw - | \\[\\`*_{}\[\]()#.!+\->]?+ # Escapes - | \[ - ( - (?<square> # Named group - [^\[\]\\] # Match most chars - | \\. # Escaped chars - | \[ \g<square>*+ \] # Nested brackets - )*+ - \] - ( - ( # Reference Link - [ ]? # Optional space - \[[^\]]*+\] # Ref name - ) - | ( # Inline Link - \( # Opening paren - [ \t]*+ # Optional whtiespace - <?(.*?)>? # URL - [ \t]*+ # Optional whtiespace - ( # Optional Title - (?<title>['"]) - (.*?) - \k<title> - )? - \) - ) - ) - ) - | (?!(?<=\S)\1). # Everything besides - # style closer - )++ - (?<=\S)\1 # Close - ) - - captures - - 1 - - name - punctuation.definition.bold.markdown - - - end - (?<=\S)(\1) - name - markup.bold.markdown - patterns - - - applyEndPatternLast - 1 - begin - (?=<[^>]*?>) - end - (?<=>) - patterns - - - include - text.html.basic - - - - - include - #escape - - - include - #ampersand - - - include - #bracket - - - include - #raw - - - include - #italic - - - include - #image-inline - - - include - #link-inline - - - include - #link-inet - - - include - #link-email - - - include - #image-ref - - - include - #link-ref-literal - - - include - #link-ref - - - - bracket - - comment - - Markdown will convert this for us. We match it so that the - HTML grammar will not mark it up as invalid. - - match - <(?![a-z/?\$!]) - name - meta.other.valid-bracket.markdown - - escape - - match - \\[-`*_#+.!(){}\[\]\\>] - name - constant.character.escape.markdown - - image-inline - - captures - - 1 - - name - punctuation.definition.string.begin.markdown - - 10 - - name - string.other.link.description.title.markdown - - 11 - - name - punctuation.definition.string.markdown - - 12 - - name - punctuation.definition.string.markdown - - 13 - - name - string.other.link.description.title.markdown - - 14 - - name - punctuation.definition.string.markdown - - 15 - - name - punctuation.definition.string.markdown - - 16 - - name - punctuation.definition.metadata.markdown - - 2 - - name - string.other.link.description.markdown - - 4 - - name - punctuation.definition.string.end.markdown - - 5 - - name - invalid.illegal.whitespace.markdown - - 6 - - name - punctuation.definition.metadata.markdown - - 7 - - name - punctuation.definition.link.markdown - - 8 - - name - markup.underline.link.image.markdown - - 9 - - name - punctuation.definition.link.markdown - - - match - (?x: - \! # Images start with ! - (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\]) - # Match the link text. - ([ ])? # Space not allowed - (\() # Opening paren for url - (<?)(\S+?)(>?) # The url - [ \t]* # Optional whitespace - (?: - ((\().+?(\))) # Match title in parens… - | ((").+?(")) # or in quotes. - )? # Title is optional - \s* # Optional whitespace - (\)) - ) - name - meta.image.inline.markdown - - image-ref - - captures - - 1 - - name - punctuation.definition.string.begin.markdown - - 2 - - name - string.other.link.description.markdown - - 4 - - name - punctuation.definition.string.begin.markdown - - 5 - - name - punctuation.definition.constant.markdown - - 6 - - name - constant.other.reference.link.markdown - - 7 - - name - punctuation.definition.constant.markdown - - - match - \!(\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)(.*?)(\]) - name - meta.image.reference.markdown - - italic - - begin - (?x) - (\*|_)(?=\S) # Open - (?= - ( - <[^>]*+> # HTML tags - | (?<raw>`+)([^`]|(?!(?<!`)\k<raw>(?!`))`)*+\k<raw> - # Raw - | \\[\\`*_{}\[\]()#.!+\->]?+ # Escapes - | \[ - ( - (?<square> # Named group - [^\[\]\\] # Match most chars - | \\. # Escaped chars - | \[ \g<square>*+ \] # Nested brackets - )*+ - \] - ( - ( # Reference Link - [ ]? # Optional space - \[[^\]]*+\] # Ref name - ) - | ( # Inline Link - \( # Opening paren - [ \t]*+ # Optional whtiespace - <?(.*?)>? # URL - [ \t]*+ # Optional whtiespace - ( # Optional Title - (?<title>['"]) - (.*?) - \k<title> - )? - \) - ) - ) - ) - | \1\1 # Must be bold closer - | (?!(?<=\S)\1). # Everything besides - # style closer - )++ - (?<=\S)\1 # Close - ) - - captures - - 1 - - name - punctuation.definition.italic.markdown - - - end - (?<=\S)(\1)((?!\1)|(?=\1\1)) - name - markup.italic.markdown - patterns - - - applyEndPatternLast - 1 - begin - (?=<[^>]*?>) - end - (?<=>) - patterns - - - include - text.html.basic - - - - - include - #escape - - - include - #ampersand - - - include - #bracket - - - include - #raw - - - include - #bold - - - include - #image-inline - - - include - #link-inline - - - include - #link-inet - - - include - #link-email - - - include - #image-ref - - - include - #link-ref-literal - - - include - #link-ref - - - - link-email - - captures - - 1 - - name - punctuation.definition.link.markdown - - 2 - - name - markup.underline.link.markdown - - 4 - - name - punctuation.definition.link.markdown - - - match - (<)((?:mailto:)?[-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(>) - name - meta.link.email.lt-gt.markdown - - link-inet - - captures - - 1 - - name - punctuation.definition.link.markdown - - 2 - - name - markup.underline.link.markdown - - 3 - - name - punctuation.definition.link.markdown - - - match - (<)((?:https?|ftp)://.*?)(>) - name - meta.link.inet.markdown - - link-inline - - captures - - 1 - - name - punctuation.definition.string.begin.markdown - - 10 - - name - string.other.link.description.title.markdown - - 11 - - name - punctuation.definition.string.begin.markdown - - 12 - - name - punctuation.definition.string.end.markdown - - 13 - - name - string.other.link.description.title.markdown - - 14 - - name - punctuation.definition.string.begin.markdown - - 15 - - name - punctuation.definition.string.end.markdown - - 16 - - name - punctuation.definition.metadata.markdown - - 2 - - name - string.other.link.title.markdown - - 4 - - name - punctuation.definition.string.end.markdown - - 5 - - name - invalid.illegal.whitespace.markdown - - 6 - - name - punctuation.definition.metadata.markdown - - 7 - - name - punctuation.definition.link.markdown - - 8 - - name - markup.underline.link.markdown - - 9 - - name - punctuation.definition.link.markdown - - - match - (?x: - (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\]) - # Match the link text. - ([ ])? # Space not allowed - (\() # Opening paren for url - (<?)(.*?)(>?) # The url - [ \t]* # Optional whitespace - (?: - ((\().+?(\))) # Match title in parens… - | ((").+?(")) # or in quotes. - )? # Title is optional - \s* # Optional whitespace - (\)) - ) - name - meta.link.inline.markdown - - link-ref - - captures - - 1 - - name - punctuation.definition.string.begin.markdown - - 2 - - name - string.other.link.title.markdown - - 4 - - name - punctuation.definition.string.end.markdown - - 5 - - name - punctuation.definition.constant.begin.markdown - - 6 - - name - constant.other.reference.link.markdown - - 7 - - name - punctuation.definition.constant.end.markdown - - - match - (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)([^\]]*+)(\]) - name - meta.link.reference.markdown - - link-ref-literal - - captures - - 1 - - name - punctuation.definition.string.begin.markdown - - 2 - - name - string.other.link.title.markdown - - 4 - - name - punctuation.definition.string.end.markdown - - 5 - - name - punctuation.definition.constant.begin.markdown - - 6 - - name - punctuation.definition.constant.end.markdown - - - match - (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)(\]) - name - meta.link.reference.literal.markdown - - raw - - captures - - 1 - - name - punctuation.definition.raw.markdown - - 2 - - 3 - - name - punctuation.definition.raw.markdown - - - match - (`+)([^`]|(?!(?<!`)\1(?!`))`)*+(\1) - name - markup.raw.inline.markdown - - - - - scopeName - text.html.markdown - uuid - 0A1D9874-B448-11D9-BD50-000D93B6E43C - + + + + + fileTypes + + md + mdown + markdown + markdn + + keyEquivalent + ^~M + name + Markdown + patterns + + + include + #block + + + repository + + block + + patterns + + + include + #separator + + + include + #heading + + + include + #blockquote + + + include + #lists + + + include + #raw_block + + + include + #link-def + + + include + #html + + + include + #paragraph + + + repository + + blockquote + + begin + (^|\G)(>) ? + captures + + 2 + + name + punctuation.definition.quote.markdown + + + name + markup.quote.markdown + patterns + + + include + #block + + + while + (^|\G)(>) ? + + heading + + begin + (?:^|\G)(#{1,6})\s*(?=[\S[^#]]) + captures + + 1 + + name + punctuation.definition.heading.markdown + + + contentName + entity.name.section.markdown + end + \s*(#{1,6})?$\n? + name + markup.heading.markdown + patterns + + + include + #inline + + + + heading-setext + + patterns + + + match + ^(={3,})(?=[ \t]*$\n?) + name + markup.heading.setext.1.markdown + + + match + ^(-{3,})(?=[ \t]*$\n?) + name + markup.heading.setext.2.markdown + + + + html + + patterns + + + begin + (?i)(^|\G)(?=<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del).*</\2\s*>\s*$) + end + $ + patterns + + + include + text.html.basic + + + + + begin + (?i)(^|\G)(?=<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)) + patterns + + + include + text.html.basic + + + while + \G(?!</\2\s*>) + + + + link-def + + captures + + 1 + + name + punctuation.definition.constant.markdown + + 10 + + name + punctuation.definition.string.end.markdown + + 11 + + name + string.other.link.description.title.markdown + + 12 + + name + punctuation.definition.string.begin.markdown + + 13 + + name + punctuation.definition.string.end.markdown + + 2 + + name + constant.other.reference.link.markdown + + 3 + + name + punctuation.definition.constant.markdown + + 4 + + name + punctuation.separator.key-value.markdown + + 5 + + name + punctuation.definition.link.markdown + + 6 + + name + markup.underline.link.markdown + + 7 + + name + punctuation.definition.link.markdown + + 8 + + name + string.other.link.description.title.markdown + + 9 + + name + punctuation.definition.string.begin.markdown + + + match + ^(?x: + \s* # Leading whitespace + (\[)(.+?)(\])(:) # Reference name + [ \t]* # Optional whitespace + (<?)(\S+?)(>?) # The url + [ \t]* # Optional whitespace + (?: + ((\().+?(\))) # Match title in quotes… + | ((").+?(")) # or in parens. + )? # Title is optional + \s* # Optional whitespace + $ + ) + name + meta.link.reference.def.markdown + + list_paragraph + + begin + (^|\G)(?=\S)(?![*+-]\s|[0-9]+\.\s) + name + meta.paragraph.markdown + patterns + + + include + #inline + + + include + text.html.basic + + + include + #heading-setext + + + while + (^|\G)(?!\s*$|#|[ ]{0,3}([-*_][ ]{2,}){3,}[ \t]*$\n?|>|[ ]{0,3}[*+-]|[ ]{0,3}[0-9]+\.) + + lists + + patterns + + + begin + (^|\G)([ ]{0,3})([*+-])([ ]{1,3}|\t) + beginCaptures + + 3 + + name + punctuation.definition.list.markdown + + + comment + Currently does not support un-indented second lines. + name + markup.list.unnumbered.markdown + patterns + + + include + #list_paragraph + + + include + #block + + + while + \G([ ]{4}|\t|$) + + + begin + (^|\G)([ ]{0,3})([0-9]+\.)([ ]{1,3}|\t) + beginCaptures + + 3 + + name + punctuation.definition.list.markdown + + + name + markup.list.numbered.markdown + patterns + + + include + #list_paragraph + + + include + #block + + + while + \G([ ]{4}|\t|$) + + + + paragraph + + begin + (^|\G)(?=\S) + name + meta.paragraph.markdown + patterns + + + include + #inline + + + include + text.html.basic + + + include + #heading-setext + + + while + (^|\G)(?!\s*$|#|[ ]{0,3}([-*_][ ]{2,}){3,}[ \t]*$\n?|\s*\[.+?\]:|>) + + raw_block + + begin + (^|\G)([ ]{4}|\t) + name + markup.raw.block.markdown + while + (^|\G)([ ]{4}|\t) + + separator + + match + (^|\G)[ ]{0,3}([-*_])([ ]{0,2}\2){2,}[ \t]*$\n? + name + meta.separator.markdown + + + + inline + + patterns + + + include + #ampersand + + + include + #bracket + + + include + #bold + + + include + #italic + + + include + #raw + + + include + #escape + + + include + #image-inline + + + include + #image-ref + + + include + #link-email + + + include + #link-inet + + + include + #link-inline + + + include + #link-ref + + + include + #link-ref-literal + + + repository + + ampersand + + comment + + Markdown will convert this for us. We match it so that the + HTML grammar will not mark it up as invalid. + + match + &(?!([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+);) + name + meta.other.valid-ampersand.markdown + + bold + + begin + (?x) + (\*\*|__)(?=\S) # Open + (?= + ( + <[^>]*+> # HTML tags + | (?<raw>`+)([^`]|(?!(?<!`)\k<raw>(?!`))`)*+\k<raw> + # Raw + | \\[\\`*_{}\[\]()#.!+\->]?+ # Escapes + | \[ + ( + (?<square> # Named group + [^\[\]\\] # Match most chars + | \\. # Escaped chars + | \[ \g<square>*+ \] # Nested brackets + )*+ + \] + ( + ( # Reference Link + [ ]? # Optional space + \[[^\]]*+\] # Ref name + ) + | ( # Inline Link + \( # Opening paren + [ \t]*+ # Optional whtiespace + <?(.*?)>? # URL + [ \t]*+ # Optional whtiespace + ( # Optional Title + (?<title>['"]) + (.*?) + \k<title> + )? + \) + ) + ) + ) + | (?!(?<=\S)\1). # Everything besides + # style closer + )++ + (?<=\S)\1 # Close + ) + + captures + + 1 + + name + punctuation.definition.bold.markdown + + + end + (?<=\S)(\1) + name + markup.bold.markdown + patterns + + + applyEndPatternLast + 1 + begin + (?=<[^>]*?>) + end + (?<=>) + patterns + + + include + text.html.basic + + + + + include + #escape + + + include + #ampersand + + + include + #bracket + + + include + #raw + + + include + #italic + + + include + #image-inline + + + include + #link-inline + + + include + #link-inet + + + include + #link-email + + + include + #image-ref + + + include + #link-ref-literal + + + include + #link-ref + + + + bracket + + comment + + Markdown will convert this for us. We match it so that the + HTML grammar will not mark it up as invalid. + + match + <(?![a-z/?\$!]) + name + meta.other.valid-bracket.markdown + + escape + + match + \\[-`*_#+.!(){}\[\]\\>] + name + constant.character.escape.markdown + + image-inline + + captures + + 1 + + name + punctuation.definition.string.begin.markdown + + 10 + + name + string.other.link.description.title.markdown + + 11 + + name + punctuation.definition.string.markdown + + 12 + + name + punctuation.definition.string.markdown + + 13 + + name + string.other.link.description.title.markdown + + 14 + + name + punctuation.definition.string.markdown + + 15 + + name + punctuation.definition.string.markdown + + 16 + + name + punctuation.definition.metadata.markdown + + 2 + + name + string.other.link.description.markdown + + 4 + + name + punctuation.definition.string.end.markdown + + 5 + + name + invalid.illegal.whitespace.markdown + + 6 + + name + punctuation.definition.metadata.markdown + + 7 + + name + punctuation.definition.link.markdown + + 8 + + name + markup.underline.link.image.markdown + + 9 + + name + punctuation.definition.link.markdown + + + match + (?x: + \! # Images start with ! + (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\]) + # Match the link text. + ([ ])? # Space not allowed + (\() # Opening paren for url + (<?)(\S+?)(>?) # The url + [ \t]* # Optional whitespace + (?: + ((\().+?(\))) # Match title in parens… + | ((").+?(")) # or in quotes. + )? # Title is optional + \s* # Optional whitespace + (\)) + ) + name + meta.image.inline.markdown + + image-ref + + captures + + 1 + + name + punctuation.definition.string.begin.markdown + + 2 + + name + string.other.link.description.markdown + + 4 + + name + punctuation.definition.string.begin.markdown + + 5 + + name + punctuation.definition.constant.markdown + + 6 + + name + constant.other.reference.link.markdown + + 7 + + name + punctuation.definition.constant.markdown + + + match + \!(\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)(.*?)(\]) + name + meta.image.reference.markdown + + italic + + begin + (?x) + (\*|_)(?=\S) # Open + (?= + ( + <[^>]*+> # HTML tags + | (?<raw>`+)([^`]|(?!(?<!`)\k<raw>(?!`))`)*+\k<raw> + # Raw + | \\[\\`*_{}\[\]()#.!+\->]?+ # Escapes + | \[ + ( + (?<square> # Named group + [^\[\]\\] # Match most chars + | \\. # Escaped chars + | \[ \g<square>*+ \] # Nested brackets + )*+ + \] + ( + ( # Reference Link + [ ]? # Optional space + \[[^\]]*+\] # Ref name + ) + | ( # Inline Link + \( # Opening paren + [ \t]*+ # Optional whtiespace + <?(.*?)>? # URL + [ \t]*+ # Optional whtiespace + ( # Optional Title + (?<title>['"]) + (.*?) + \k<title> + )? + \) + ) + ) + ) + | \1\1 # Must be bold closer + | (?!(?<=\S)\1). # Everything besides + # style closer + )++ + (?<=\S)\1 # Close + ) + + captures + + 1 + + name + punctuation.definition.italic.markdown + + + end + (?<=\S)(\1)((?!\1)|(?=\1\1)) + name + markup.italic.markdown + patterns + + + applyEndPatternLast + 1 + begin + (?=<[^>]*?>) + end + (?<=>) + patterns + + + include + text.html.basic + + + + + include + #escape + + + include + #ampersand + + + include + #bracket + + + include + #raw + + + include + #bold + + + include + #image-inline + + + include + #link-inline + + + include + #link-inet + + + include + #link-email + + + include + #image-ref + + + include + #link-ref-literal + + + include + #link-ref + + + + link-email + + captures + + 1 + + name + punctuation.definition.link.markdown + + 2 + + name + markup.underline.link.markdown + + 4 + + name + punctuation.definition.link.markdown + + + match + (<)((?:mailto:)?[-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(>) + name + meta.link.email.lt-gt.markdown + + link-inet + + captures + + 1 + + name + punctuation.definition.link.markdown + + 2 + + name + markup.underline.link.markdown + + 3 + + name + punctuation.definition.link.markdown + + + match + (<)((?:https?|ftp)://.*?)(>) + name + meta.link.inet.markdown + + link-inline + + captures + + 1 + + name + punctuation.definition.string.begin.markdown + + 10 + + name + string.other.link.description.title.markdown + + 11 + + name + punctuation.definition.string.begin.markdown + + 12 + + name + punctuation.definition.string.end.markdown + + 13 + + name + string.other.link.description.title.markdown + + 14 + + name + punctuation.definition.string.begin.markdown + + 15 + + name + punctuation.definition.string.end.markdown + + 16 + + name + punctuation.definition.metadata.markdown + + 2 + + name + string.other.link.title.markdown + + 4 + + name + punctuation.definition.string.end.markdown + + 5 + + name + invalid.illegal.whitespace.markdown + + 6 + + name + punctuation.definition.metadata.markdown + + 7 + + name + punctuation.definition.link.markdown + + 8 + + name + markup.underline.link.markdown + + 9 + + name + punctuation.definition.link.markdown + + + match + (?x: + (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\]) + # Match the link text. + ([ ])? # Space not allowed + (\() # Opening paren for url + (<?)(.*?)(>?) # The url + [ \t]* # Optional whitespace + (?: + ((\().+?(\))) # Match title in parens… + | ((").+?(")) # or in quotes. + )? # Title is optional + \s* # Optional whitespace + (\)) + ) + name + meta.link.inline.markdown + + link-ref + + captures + + 1 + + name + punctuation.definition.string.begin.markdown + + 2 + + name + string.other.link.title.markdown + + 4 + + name + punctuation.definition.string.end.markdown + + 5 + + name + punctuation.definition.constant.begin.markdown + + 6 + + name + constant.other.reference.link.markdown + + 7 + + name + punctuation.definition.constant.end.markdown + + + match + (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)([^\]]*+)(\]) + name + meta.link.reference.markdown + + link-ref-literal + + captures + + 1 + + name + punctuation.definition.string.begin.markdown + + 2 + + name + string.other.link.title.markdown + + 4 + + name + punctuation.definition.string.end.markdown + + 5 + + name + punctuation.definition.constant.begin.markdown + + 6 + + name + punctuation.definition.constant.end.markdown + + + match + (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)(\]) + name + meta.link.reference.literal.markdown + + raw + + captures + + 1 + + name + punctuation.definition.raw.markdown + + 2 + + 3 + + name + punctuation.definition.raw.markdown + + + match + (`+)([^`]|(?!(?<!`)\1(?!`))`)*+(\1) + name + markup.raw.inline.markdown + + + + + scopeName + text.html.markdown + uuid + 0A1D9874-B448-11D9-BD50-000D93B6E43C + \ No newline at end of file diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/Perl.plist b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Perl.plist similarity index 95% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/Perl.plist rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Perl.plist index d259fcb9c..beab27aad 100644 --- a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/Perl.plist +++ b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Perl.plist @@ -1,3690 +1,3690 @@ - - - - - comment - - TODO: Include RegExp syntax - - fileTypes - - pl - pm - pod - t - PL - psgi - - firstLineMatch - ^#!.*\bperl\b - keyEquivalent - ^~P - name - Perl - patterns - - - include - #line_comment - - - begin - ^= - captures - - 0 - - name - punctuation.definition.comment.perl - - - end - ^=cut - name - comment.block.documentation.perl - - - include - #variable - - - applyEndPatternLast - 1 - begin - \b(?=qr\s*[^\s\w]) - comment - string.regexp.compile.perl - end - ((([egimosxradlupc]*)))(?=(\s+\S|\s*[;\,\#\{\}\)]|$)) - endCaptures - - 1 - - name - string.regexp.compile.perl - - 2 - - name - punctuation.definition.string.perl - - 3 - - name - keyword.control.regexp-option.perl - - - patterns - - - begin - (qr)\s*\{ - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - \} - name - string.regexp.compile.nested_braces.perl - patterns - - - include - #escaped_char - - - include - #variable - - - include - #nested_braces_interpolated - - - - - begin - (qr)\s*\[ - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - \] - name - string.regexp.compile.nested_brackets.perl - patterns - - - include - #escaped_char - - - include - #variable - - - include - #nested_brackets_interpolated - - - - - begin - (qr)\s*< - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - > - name - string.regexp.compile.nested_ltgt.perl - patterns - - - include - #escaped_char - - - include - #variable - - - include - #nested_ltgt_interpolated - - - - - begin - (qr)\s*\( - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - \) - name - string.regexp.compile.nested_parens.perl - patterns - - - comment - This is to prevent thinks like qr/foo$/ to treat $/ as a variable - match - \$(?=[^\s\w\\'\{\[\(\<]) - - - include - #escaped_char - - - include - #variable - - - include - #nested_parens_interpolated - - - - - begin - (qr)\s*' - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - ' - name - string.regexp.compile.single-quote.perl - patterns - - - include - #escaped_char - - - - - begin - (qr)\s*([^\s\w'\{\[\(\<]) - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - \2 - name - string.regexp.compile.simple-delimiter.perl - patterns - - - comment - This is to prevent thinks like qr/foo$/ to treat $/ as a variable - match - \$(?=[^\s\w'\{\[\(\<]) - name - keyword.control.anchor.perl - - - include - #escaped_char - - - include - #variable - - - include - #nested_parens_interpolated - - - - - - - applyEndPatternLast - 1 - begin - \b(?=m\s*[^\sa-zA-Z0-9]) - comment - string.regexp.find-m.perl - end - ((([egimosxradlupc]*)))(?=(\s+\S|\s*[;\,\#\{\}\)]|$)) - endCaptures - - 1 - - name - string.regexp.find-m.perl - - 2 - - name - punctuation.definition.string.perl - - 3 - - name - keyword.control.regexp-option.perl - - - patterns - - - begin - (m)\s*\{ - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - \} - name - string.regexp.find-m.nested_braces.perl - patterns - - - include - #escaped_char - - - include - #variable - - - include - #nested_braces_interpolated - - - - - begin - (m)\s*\[ - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - \] - name - string.regexp.find-m.nested_brackets.perl - patterns - - - include - #escaped_char - - - include - #variable - - - include - #nested_brackets_interpolated - - - - - begin - (m)\s*< - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - > - name - string.regexp.find-m.nested_ltgt.perl - patterns - - - include - #escaped_char - - - include - #variable - - - include - #nested_ltgt_interpolated - - - - - begin - (m)\s*\( - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - \) - name - string.regexp.find-m.nested_parens.perl - patterns - - - include - #escaped_char - - - include - #variable - - - include - #nested_parens_interpolated - - - - - begin - (m)\s*' - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - ' - name - string.regexp.find-m.single-quote.perl - patterns - - - include - #escaped_char - - - - - begin - (m)\s*([^\sa-zA-Z0-9'\{\[\(\<]) - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - \2 - name - string.regexp.find-m.simple-delimiter.perl - patterns - - - comment - This is to prevent thinks like qr/foo$/ to treat $/ as a variable - match - \$(?=[^\sa-zA-Z0-9'\{\[\(\<]) - name - keyword.control.anchor.perl - - - include - #escaped_char - - - include - #variable - - - begin - \[ - beginCaptures - - 1 - - name - punctuation.definition.character-class.begin.perl - - - end - \] - endCaptures - - 1 - - name - punctuation.definition.character-class.end.perl - - - name - constant.other.character-class.set.perl - patterns - - - comment - This is to prevent thinks like qr/foo$/ to treat $/ as a variable - match - \$(?=[^\s\w'\{\[\(\<]) - name - keyword.control.anchor.perl - - - include - #escaped_char - - - - - include - #nested_parens_interpolated - - - - - - - applyEndPatternLast - 1 - begin - \b(?=(?<!\&)(s)(\s+\S|\s*[;\,\#\{\}\(\)\[<]|$)) - comment - string.regexp.replace.perl - end - ((([egimosxradlupc]*)))(?=(\s+\S|\s*[;\,\#\{\}\)\]>]|$)) - endCaptures - - 1 - - name - string.regexp.replace.perl - - 2 - - name - punctuation.definition.string.perl - - 3 - - name - keyword.control.regexp-option.perl - - - patterns - - - begin - (s)\s*\{ - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - \} - name - string.regexp.nested_braces.perl - patterns - - - include - #escaped_char - - - include - #nested_braces - - - - - begin - (s)\s*\[ - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - \] - name - string.regexp.nested_brackets.perl - patterns - - - include - #escaped_char - - - include - #nested_brackets - - - - - begin - (s)\s*< - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - > - name - string.regexp.nested_ltgt.perl - patterns - - - include - #escaped_char - - - include - #nested_ltgt - - - - - begin - (s)\s*\( - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - \) - name - string.regexp.nested_parens.perl - patterns - - - include - #escaped_char - - - include - #nested_parens - - - - - begin - \{ - captures - - 0 - - name - punctuation.definition.string.perl - - - end - \} - name - string.regexp.format.nested_braces.perl - patterns - - - include - #escaped_char - - - include - #variable - - - include - #nested_braces_interpolated - - - - - begin - \[ - captures - - 0 - - name - punctuation.definition.string.perl - - - end - \] - name - string.regexp.format.nested_brackets.perl - patterns - - - include - #escaped_char - - - include - #variable - - - include - #nested_brackets_interpolated - - - - - begin - < - captures - - 0 - - name - punctuation.definition.string.perl - - - end - > - name - string.regexp.format.nested_ltgt.perl - patterns - - - include - #escaped_char - - - include - #variable - - - include - #nested_ltgt_interpolated - - - - - begin - \( - captures - - 0 - - name - punctuation.definition.string.perl - - - end - \) - name - string.regexp.format.nested_parens.perl - patterns - - - include - #escaped_char - - - include - #variable - - - include - #nested_parens_interpolated - - - - - begin - ' - captures - - 0 - - name - punctuation.definition.string.perl - - - end - ' - name - string.regexp.format.single_quote.perl - patterns - - - match - \\['\\] - name - constant.character.escape.perl - - - - - begin - ([^\s\w\[({<;]) - captures - - 0 - - name - punctuation.definition.string.perl - - - end - \1 - name - string.regexp.format.simple_delimiter.perl - patterns - - - include - #escaped_char - - - include - #variable - - - - - match - \s+ - - - - - begin - \b(?=s([^\sa-zA-Z0-9\[({<]).*\1([egimosxradlupc]*)([\}\)\;\,]|\s+)) - comment - string.regexp.replaceXXX - end - ((([egimosxradlupc]*)))(?=([\}\)\;\,]|\s+|$)) - endCaptures - - 1 - - name - string.regexp.replace.perl - - 2 - - name - punctuation.definition.string.perl - - 3 - - name - keyword.control.regexp-option.perl - - - patterns - - - begin - (s\s*)([^\sa-zA-Z0-9\[({<]) - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - (?=\2) - name - string.regexp.replaceXXX.simple_delimiter.perl - patterns - - - include - #escaped_char - - - - - begin - ' - captures - - 0 - - name - punctuation.definition.string.perl - - - end - ' - name - string.regexp.replaceXXX.format.single_quote.perl - patterns - - - match - \\['\\] - name - constant.character.escape.perl.perl - - - - - begin - ([^\sa-zA-Z0-9\[({<]) - captures - - 0 - - name - punctuation.definition.string.perl - - - end - \1 - name - string.regexp.replaceXXX.format.simple_delimiter.perl - patterns - - - include - #escaped_char - - - include - #variable - - - - - - - begin - \b(?=(?<!\\)s\s*([^\s\w\[({<>])) - comment - string.regexp.replace.extended - end - \2((([egimosradlupc]*x[egimosradlupc]*)))\b - endCaptures - - 1 - - name - string.regexp.replace.perl - - 2 - - name - punctuation.definition.string.perl - - 3 - - name - keyword.control.regexp-option.perl - - - patterns - - - begin - (s)\s*(.) - captures - - 0 - - name - punctuation.definition.string.perl - - 1 - - name - support.function.perl - - - end - (?=\2) - name - string.regexp.replace.extended.simple_delimiter.perl - patterns - - - include - #escaped_char - - - - - begin - ' - captures - - 0 - - name - punctuation.definition.string.perl - - - end - '(?=[egimosradlupc]*x[egimosradlupc]*)\b - name - string.regexp.replace.extended.simple_delimiter.perl - patterns - - - include - #escaped_char - - - - - begin - (.) - captures - - 0 - - name - punctuation.definition.string.perl - - - end - \1(?=[egimosradlupc]*x[egimosradlupc]*)\b - name - string.regexp.replace.extended.simple_delimiter.perl - patterns - - - include - #escaped_char - - - include - #variable - - - - - - - begin - (?<=\(|\{|~|&)\s*((\/)) - beginCaptures - - 1 - - name - string.regexp.find.perl - - 2 - - name - punctuation.definition.string.perl - - - contentName - string.regexp.find.perl - end - ((\1([egimosxradlupc]*)))(?=(\s+\S|\s*[;\,\#\{\}\)]|$)) - endCaptures - - 1 - - name - string.regexp.find.perl - - 2 - - name - punctuation.definition.string.perl - - 3 - - name - keyword.control.regexp-option.perl - - - patterns - - - comment - This is to prevent thinks like /foo$/ to treat $/ as a variable - match - \$(?=\/) - name - keyword.control.anchor.perl - - - include - #escaped_char - - - include - #variable - - - - - captures - - 1 - - name - constant.other.key.perl - - - match - \b(\w+)\s*(?==>) - - - match - (?<={)\s*\w+\s*(?=}) - name - constant.other.bareword.perl - - - captures - - 1 - - name - keyword.control.perl - - 2 - - name - entity.name.type.class.perl - - - match - ^\s*(package)\s+([^\s;]+) - name - meta.class.perl - - - captures - - 1 - - name - storage.type.sub.perl - - 2 - - name - entity.name.function.perl - - 3 - - name - storage.type.method.perl - - - match - \b(sub)(?:\s+([-a-zA-Z0-9_]+))?\s*(?:\([\$\@\*;]*\))?[^\w\{] - name - meta.function.perl - - - captures - - 1 - - name - entity.name.function.perl - - 2 - - name - punctuation.definition.parameters.perl - - 3 - - name - variable.parameter.function.perl - - - match - ^\s*(BEGIN|UNITCHECK|CHECK|INIT|END|DESTROY)\b - name - meta.function.perl - - - begin - ^(?=(\t| {4})) - end - (?=[^\t\s]) - name - meta.leading-tabs - patterns - - - captures - - 1 - - name - meta.odd-tab - - 2 - - name - meta.even-tab - - - match - (\t| {4})(\t| {4})? - - - - - captures - - 1 - - name - support.function.perl - - 2 - - name - punctuation.definition.string.perl - - 5 - - name - punctuation.definition.string.perl - - 8 - - name - punctuation.definition.string.perl - - - match - \b(tr|y)\s*([^A-Za-z0-9\s])(.*?)(?<!\\)(\\{2})*(\2)(.*?)(?<!\\)(\\{2})*(\2) - name - string.regexp.replace.perl - - - match - \b(__FILE__|__LINE__|__PACKAGE__|__SUB__|__DATA__|__END__)\b - name - constant.language.perl - - - match - (?<!->)\b(continue|die|do|else|elsif|exit|for|foreach|goto|if|last|next|redo|return|select|unless|until|wait|while|switch|case|require|use|eval)\b - name - keyword.control.perl - - - match - \b(my|our|local)\b - name - storage.modifier.perl - - - match - (?<!\w)\-[rwx0RWXOezsfdlpSbctugkTBMAC]\b - name - keyword.operator.filetest.perl - - - match - \b(and|or|xor|as|not)\b - name - keyword.operator.logical.perl - - - match - (<=>|=>|->) - name - keyword.operator.comparison.perl - - - begin - (((<<) *"HTML"))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.doublequote.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - text.html.embedded.perl - end - (^HTML$) - patterns - - - include - #escaped_char - - - include - #variable - - - include - text.html.basic - - - - - begin - (((<<) *"XML"))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.doublequote.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - text.xml.embedded.perl - end - (^XML$) - patterns - - - include - #escaped_char - - - include - #variable - - - include - text.xml - - - - - begin - (((<<) *"CSS"))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.doublequote.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - text.css.embedded.perl - end - (^CSS$) - patterns - - - include - #escaped_char - - - include - #variable - - - include - source.css - - - - - begin - (((<<) *"JAVASCRIPT"))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.doublequote.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - text.js.embedded.perl - end - (^JAVASCRIPT$) - patterns - - - include - #escaped_char - - - include - #variable - - - include - source.js - - - - - begin - (((<<) *"SQL"))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.doublequote.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - source.sql.embedded.perl - end - (^SQL$) - patterns - - - include - #escaped_char - - - include - #variable - - - include - source.sql - - - - - begin - (((<<) *"POSTSCRIPT"))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.doublequote.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - text.postscript.embedded.perl - end - (^POSTSCRIPT$) - patterns - - - include - #escaped_char - - - include - #variable - - - include - source.postscript - - - - - begin - (((<<) *"([^"]*)"))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.doublequote.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - string.unquoted.heredoc.doublequote.perl - end - (^\4$) - patterns - - - include - #escaped_char - - - include - #variable - - - - - begin - (((<<) *'HTML'))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.quote.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - text.html.embedded.perl - end - (^HTML$) - patterns - - - include - text.html.basic - - - - - begin - (((<<) *'XML'))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.quote.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - text.xml.embedded.perl - end - (^XML$) - patterns - - - include - text.xml - - - - - begin - (((<<) *'CSS'))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.quote.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - text.css.embedded.perl - end - (^CSS$) - patterns - - - include - source.css - - - - - begin - (((<<) *'JAVASCRIPT'))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.quote.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - text.js.embedded.perl - end - (^JAVASCRIPT$) - patterns - - - include - source.js - - - - - begin - (((<<) *'SQL'))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.quote.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - source.sql.embedded.perl - end - (^SQL$) - patterns - - - include - source.sql - - - - - begin - (((<<) *'POSTSCRIPT'))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.quote.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - source.postscript.embedded.perl - end - (^POSTSCRIPT$) - patterns - - - include - source.postscript - - - - - begin - (((<<) *'([^']*)'))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.quote.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - string.unquoted.heredoc.quote.perl - end - (^\4$) - - - begin - (((<<) *\\((?![=\d\$\( ])[^;,'"`\s\)]*)))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.quote.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - string.unquoted.heredoc.quote.perl - end - (^\4$) - - - begin - (((<<) *`([^`]*)`))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.backtick.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - string.unquoted.heredoc.backtick.perl - end - (^\4$) - patterns - - - include - #escaped_char - - - include - #variable - - - - - begin - (((<<) *HTML\b))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - text.html.embedded.perl - end - (^HTML$) - patterns - - - include - #escaped_char - - - include - #variable - - - include - text.html.basic - - - - - begin - (((<<) *XML\b))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - text.xml.embedded.perl - end - (^XML$) - patterns - - - include - #escaped_char - - - include - #variable - - - include - text.xml - - - - - begin - (((<<) *JAVASCRIPT\b))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - source.js.embedded.perl - end - (^JAVASCRIPT$) - patterns - - - include - #escaped_char - - - include - #variable - - - include - source.js - - - - - begin - (((<<) *SQL\b))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - source.sql.embedded.perl - end - (^SQL$) - patterns - - - include - #escaped_char - - - include - #variable - - - include - source.sql - - - - - begin - (((<<) *POSTSCRIPT\b))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 4 - - patterns - - - include - $self - - - - - contentName - source.postscript.embedded.perl - end - (^POSTSCRIPT$) - patterns - - - include - #escaped_char - - - include - #variable - - - include - source.postscript - - - - - begin - (((<<) *((?![=\d\$\( ])[^;,'"`\s\)]*)))(.*)\n? - captures - - 1 - - name - punctuation.definition.string.perl - - 2 - - name - string.unquoted.heredoc.perl - - 3 - - name - punctuation.definition.heredoc.perl - - 5 - - patterns - - - include - $self - - - - - contentName - string.unquoted.heredoc.perl - end - (^\4$) - patterns - - - include - #escaped_char - - - include - #variable - - - - - begin - \bqq\s*([^\(\{\[\<\w\s]) - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - \1 - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.quoted.other.qq.perl - patterns - - - include - #escaped_char - - - include - #variable - - - - - begin - \bqx\s*([^'\(\{\[\<\w\s]) - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - \1 - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.interpolated.qx.perl - patterns - - - include - #escaped_char - - - include - #variable - - - - - begin - \bqx\s*' - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - ' - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.interpolated.qx.single-quote.perl - patterns - - - include - #escaped_char - - - - - begin - " - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - " - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.quoted.double.perl - patterns - - - include - #escaped_char - - - include - #variable - - - - - begin - (?<!->)\bqw?\s*([^\(\{\[\<\w\s]) - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - \1 - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.quoted.other.q.perl - - - begin - ' - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - ' - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.quoted.single.perl - patterns - - - match - \\['\\] - name - constant.character.escape.perl - - - - - begin - ` - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - ` - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.interpolated.perl - patterns - - - include - #escaped_char - - - include - #variable - - - - - begin - (?<!->)\bqq\s*\( - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - \) - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.quoted.other.qq-paren.perl - patterns - - - include - #escaped_char - - - include - #nested_parens_interpolated - - - include - #variable - - - - - begin - \bqq\s*\{ - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - \} - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.quoted.other.qq-brace.perl - patterns - - - include - #escaped_char - - - include - #nested_braces_interpolated - - - include - #variable - - - - - begin - \bqq\s*\[ - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - \] - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.quoted.other.qq-bracket.perl - patterns - - - include - #escaped_char - - - include - #nested_brackets_interpolated - - - include - #variable - - - - - begin - \bqq\s*\< - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - \> - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.quoted.other.qq-ltgt.perl - patterns - - - include - #escaped_char - - - include - #nested_ltgt_interpolated - - - include - #variable - - - - - begin - (?<!->)\bqx\s*\( - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - \) - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.interpolated.qx-paren.perl - patterns - - - include - #escaped_char - - - include - #nested_parens_interpolated - - - include - #variable - - - - - begin - \bqx\s*\{ - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - \} - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.interpolated.qx-brace.perl - patterns - - - include - #escaped_char - - - include - #nested_braces_interpolated - - - include - #variable - - - - - begin - \bqx\s*\[ - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - \] - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.interpolated.qx-bracket.perl - patterns - - - include - #escaped_char - - - include - #nested_brackets_interpolated - - - include - #variable - - - - - begin - \bqx\s*\< - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - \> - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.interpolated.qx-ltgt.perl - patterns - - - include - #escaped_char - - - include - #nested_ltgt_interpolated - - - include - #variable - - - - - begin - (?<!->)\bqw?\s*\( - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - \) - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.quoted.other.q-paren.perl - patterns - - - include - #nested_parens - - - - - begin - \bqw?\s*\{ - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - \} - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.quoted.other.q-brace.perl - patterns - - - include - #nested_braces - - - - - begin - \bqw?\s*\[ - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - \] - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.quoted.other.q-bracket.perl - patterns - - - include - #nested_brackets - - - - - begin - \bqw?\s*\< - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - \> - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.quoted.other.q-ltgt.perl - patterns - - - include - #nested_ltgt - - - - - begin - ^__\w+__ - beginCaptures - - 0 - - name - punctuation.definition.string.begin.perl - - - end - $ - endCaptures - - 0 - - name - punctuation.definition.string.end.perl - - - name - string.unquoted.program-block.perl - - - begin - \b(format)\s+(\w+)\s*= - beginCaptures - - 1 - - name - support.function.perl - - 2 - - name - entity.name.function.format.perl - - - end - ^\.\s*$ - name - meta.format.perl - patterns - - - include - #line_comment - - - include - #variable - - - - - captures - - 1 - - name - support.function.perl - - 2 - - name - entity.name.function.perl - - - match - \b(x)\s*(\d+)\b - - - match - \b(ARGV|DATA|ENV|SIG|STDERR|STDIN|STDOUT|atan2|bind|binmode|bless|caller|chdir|chmod|chomp|chop|chown|chr|chroot|close|closedir|cmp|connect|cos|crypt|dbmclose|dbmopen|defined|delete|dump|each|endgrent|endhostent|endnetent|endprotoent|endpwent|endservent|eof|eq|eval|exec|exists|exp|fcntl|fileno|flock|fork|formline|ge|getc|getgrent|getgrgid|getgrnam|gethostbyaddr|gethostbyname|gethostent|getlogin|getnetbyaddr|getnetbyname|getnetent|getpeername|getpgrp|getppid|getpriority|getprotobyname|getprotobynumber|getprotoent|getpwent|getpwnam|getpwuid|getservbyname|getservbyport|getservent|getsockname|getsockopt|glob|gmtime|grep|gt|hex|import|index|int|ioctl|join|keys|kill|lc|lcfirst|le|length|link|listen|local|localtime|log|lstat|lt|m|map|mkdir|msgctl|msgget|msgrcv|msgsnd|ne|no|oct|open|opendir|ord|pack|pipe|pop|pos|print|printf|push|quotemeta|rand|read|readdir|readlink|recv|ref|rename|reset|reverse|rewinddir|rindex|rmdir|s|scalar|seek|seekdir|semctl|semget|semop|send|setgrent|sethostent|setnetent|setpgrp|setpriority|setprotoent|setpwent|setservent|setsockopt|shift|shmctl|shmget|shmread|shmwrite|shutdown|sin|sleep|socket|socketpair|sort|splice|split|sprintf|sqrt|srand|stat|study|substr|symlink|syscall|sysopen|sysread|system|syswrite|tell|telldir|tie|tied|time|times|tr|truncate|uc|ucfirst|umask|undef|unlink|unpack|unshift|untie|utime|values|vec|waitpid|wantarray|warn|write|y)\b - name - support.function.perl - - - captures - - 1 - - name - punctuation.section.scope.begin.perl - - 2 - - name - punctuation.section.scope.end.perl - - - comment - Match empty brackets for ↩ snippet - match - (\{)(\}) - - - captures - - 1 - - name - punctuation.section.scope.begin.perl - - 2 - - name - punctuation.section.scope.end.perl - - - comment - Match empty parenthesis for ↩ snippet - match - (\()(\)) - - - repository - - escaped_char - - patterns - - - match - \\\d+ - name - constant.character.escape.perl - - - match - \\c[^\s\\] - name - constant.character.escape.perl - - - match - \\g(?:\{(?:\w*|-\d+)\}|\d+) - name - constant.character.escape.perl - - - match - \\k(?:\{\w*\}|<\w*>|'\w*') - name - constant.character.escape.perl - - - match - \\N\{[^\}]*\} - name - constant.character.escape.perl - - - match - \\o\{\d*\} - name - constant.character.escape.perl - - - match - \\(?:p|P)(?:\{\w*\}|P) - name - constant.character.escape.perl - - - match - \\x(?:[0-9a-zA-Z]{2}|\{\w*\})? - name - constant.character.escape.perl - - - match - \\. - name - constant.character.escape.perl - - - - line_comment - - patterns - - - begin - (^[ \t]+)?(?=#) - beginCaptures - - 1 - - name - punctuation.whitespace.comment.leading.perl - - - end - (?!\G) - patterns - - - begin - # - beginCaptures - - 0 - - name - punctuation.definition.comment.perl - - - end - \n - name - comment.line.number-sign.perl - - - - - - nested_braces - - begin - \{ - captures - - 1 - - name - punctuation.section.scope.perl - - - end - \} - patterns - - - include - #escaped_char - - - include - #nested_braces - - - - nested_braces_interpolated - - begin - \{ - captures - - 1 - - name - punctuation.section.scope.perl - - - end - \} - patterns - - - include - #escaped_char - - - include - #variable - - - include - #nested_braces_interpolated - - - - nested_brackets - - begin - \[ - captures - - 1 - - name - punctuation.section.scope.perl - - - end - \] - patterns - - - include - #escaped_char - - - include - #nested_brackets - - - - nested_brackets_interpolated - - begin - \[ - captures - - 1 - - name - punctuation.section.scope.perl - - - end - \] - patterns - - - include - #escaped_char - - - include - #variable - - - include - #nested_brackets_interpolated - - - - nested_ltgt - - begin - < - captures - - 1 - - name - punctuation.section.scope.perl - - - end - > - patterns - - - include - #nested_ltgt - - - - nested_ltgt_interpolated - - begin - < - captures - - 1 - - name - punctuation.section.scope.perl - - - end - > - patterns - - - include - #variable - - - include - #nested_ltgt_interpolated - - - - nested_parens - - begin - \( - captures - - 1 - - name - punctuation.section.scope.perl - - - end - \) - patterns - - - include - #escaped_char - - - include - #nested_parens - - - - nested_parens_interpolated - - begin - \( - captures - - 1 - - name - punctuation.section.scope.perl - - - end - \) - patterns - - - comment - This is to prevent thinks like qr/foo$/ to treat $/ as a variable - match - \$(?=[^\s\w'\{\[\(\<]) - name - keyword.control.anchor.perl - - - include - #escaped_char - - - include - #variable - - - include - #nested_parens_interpolated - - - - variable - - patterns - - - captures - - 1 - - name - punctuation.definition.variable.perl - - - match - (\$)&(?![A-Za-z0-9_]) - name - variable.other.regexp.match.perl - - - captures - - 1 - - name - punctuation.definition.variable.perl - - - match - (\$)`(?![A-Za-z0-9_]) - name - variable.other.regexp.pre-match.perl - - - captures - - 1 - - name - punctuation.definition.variable.perl - - - match - (\$)'(?![A-Za-z0-9_]) - name - variable.other.regexp.post-match.perl - - - captures - - 1 - - name - punctuation.definition.variable.perl - - - match - (\$)\+(?![A-Za-z0-9_]) - name - variable.other.regexp.last-paren-match.perl - - - captures - - 1 - - name - punctuation.definition.variable.perl - - - match - (\$)"(?![A-Za-z0-9_]) - name - variable.other.readwrite.list-separator.perl - - - captures - - 1 - - name - punctuation.definition.variable.perl - - - match - (\$)0(?![A-Za-z0-9_]) - name - variable.other.predefined.program-name.perl - - - captures - - 1 - - name - punctuation.definition.variable.perl - - - match - (\$)[_ab\*\.\/\|,\\;#%=\-~^:?!\$<>\(\)\[\]@](?![A-Za-z0-9_]) - name - variable.other.predefined.perl - - - captures - - 1 - - name - punctuation.definition.variable.perl - - - match - (\$)[0-9]+(?![A-Za-z0-9_]) - name - variable.other.subpattern.perl - - - captures - - 1 - - name - punctuation.definition.variable.perl - - - match - ([\$\@\%](#)?)([a-zA-Zx7f-xff\$]|::)([a-zA-Z0-9_x7f-xff\$]|::)*\b - name - variable.other.readwrite.global.perl - - - captures - - 1 - - name - punctuation.definition.variable.perl - - 2 - - name - punctuation.definition.variable.perl - - - match - (\$\{)(?:[a-zA-Zx7f-xff\$]|::)(?:[a-zA-Z0-9_x7f-xff\$]|::)*(\}) - name - variable.other.readwrite.global.perl - - - captures - - 1 - - name - punctuation.definition.variable.perl - - - match - ([\$\@\%](#)?)[0-9_]\b - name - variable.other.readwrite.global.special.perl - - - - - scopeName - source.perl - uuid - EDBFE125-6B1C-11D9-9189-000D93589AF6 - + + + + + comment + + TODO: Include RegExp syntax + + fileTypes + + pl + pm + pod + t + PL + psgi + + firstLineMatch + ^#!.*\bperl\b + keyEquivalent + ^~P + name + Perl + patterns + + + include + #line_comment + + + begin + ^= + captures + + 0 + + name + punctuation.definition.comment.perl + + + end + ^=cut + name + comment.block.documentation.perl + + + include + #variable + + + applyEndPatternLast + 1 + begin + \b(?=qr\s*[^\s\w]) + comment + string.regexp.compile.perl + end + ((([egimosxradlupc]*)))(?=(\s+\S|\s*[;\,\#\{\}\)]|$)) + endCaptures + + 1 + + name + string.regexp.compile.perl + + 2 + + name + punctuation.definition.string.perl + + 3 + + name + keyword.control.regexp-option.perl + + + patterns + + + begin + (qr)\s*\{ + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + \} + name + string.regexp.compile.nested_braces.perl + patterns + + + include + #escaped_char + + + include + #variable + + + include + #nested_braces_interpolated + + + + + begin + (qr)\s*\[ + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + \] + name + string.regexp.compile.nested_brackets.perl + patterns + + + include + #escaped_char + + + include + #variable + + + include + #nested_brackets_interpolated + + + + + begin + (qr)\s*< + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + > + name + string.regexp.compile.nested_ltgt.perl + patterns + + + include + #escaped_char + + + include + #variable + + + include + #nested_ltgt_interpolated + + + + + begin + (qr)\s*\( + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + \) + name + string.regexp.compile.nested_parens.perl + patterns + + + comment + This is to prevent thinks like qr/foo$/ to treat $/ as a variable + match + \$(?=[^\s\w\\'\{\[\(\<]) + + + include + #escaped_char + + + include + #variable + + + include + #nested_parens_interpolated + + + + + begin + (qr)\s*' + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + ' + name + string.regexp.compile.single-quote.perl + patterns + + + include + #escaped_char + + + + + begin + (qr)\s*([^\s\w'\{\[\(\<]) + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + \2 + name + string.regexp.compile.simple-delimiter.perl + patterns + + + comment + This is to prevent thinks like qr/foo$/ to treat $/ as a variable + match + \$(?=[^\s\w'\{\[\(\<]) + name + keyword.control.anchor.perl + + + include + #escaped_char + + + include + #variable + + + include + #nested_parens_interpolated + + + + + + + applyEndPatternLast + 1 + begin + \b(?=m\s*[^\sa-zA-Z0-9]) + comment + string.regexp.find-m.perl + end + ((([egimosxradlupc]*)))(?=(\s+\S|\s*[;\,\#\{\}\)]|$)) + endCaptures + + 1 + + name + string.regexp.find-m.perl + + 2 + + name + punctuation.definition.string.perl + + 3 + + name + keyword.control.regexp-option.perl + + + patterns + + + begin + (m)\s*\{ + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + \} + name + string.regexp.find-m.nested_braces.perl + patterns + + + include + #escaped_char + + + include + #variable + + + include + #nested_braces_interpolated + + + + + begin + (m)\s*\[ + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + \] + name + string.regexp.find-m.nested_brackets.perl + patterns + + + include + #escaped_char + + + include + #variable + + + include + #nested_brackets_interpolated + + + + + begin + (m)\s*< + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + > + name + string.regexp.find-m.nested_ltgt.perl + patterns + + + include + #escaped_char + + + include + #variable + + + include + #nested_ltgt_interpolated + + + + + begin + (m)\s*\( + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + \) + name + string.regexp.find-m.nested_parens.perl + patterns + + + include + #escaped_char + + + include + #variable + + + include + #nested_parens_interpolated + + + + + begin + (m)\s*' + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + ' + name + string.regexp.find-m.single-quote.perl + patterns + + + include + #escaped_char + + + + + begin + (m)\s*([^\sa-zA-Z0-9'\{\[\(\<]) + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + \2 + name + string.regexp.find-m.simple-delimiter.perl + patterns + + + comment + This is to prevent thinks like qr/foo$/ to treat $/ as a variable + match + \$(?=[^\sa-zA-Z0-9'\{\[\(\<]) + name + keyword.control.anchor.perl + + + include + #escaped_char + + + include + #variable + + + begin + \[ + beginCaptures + + 1 + + name + punctuation.definition.character-class.begin.perl + + + end + \] + endCaptures + + 1 + + name + punctuation.definition.character-class.end.perl + + + name + constant.other.character-class.set.perl + patterns + + + comment + This is to prevent thinks like qr/foo$/ to treat $/ as a variable + match + \$(?=[^\s\w'\{\[\(\<]) + name + keyword.control.anchor.perl + + + include + #escaped_char + + + + + include + #nested_parens_interpolated + + + + + + + applyEndPatternLast + 1 + begin + \b(?=(?<!\&)(s)(\s+\S|\s*[;\,\#\{\}\(\)\[<]|$)) + comment + string.regexp.replace.perl + end + ((([egimosxradlupc]*)))(?=(\s+\S|\s*[;\,\#\{\}\)\]>]|$)) + endCaptures + + 1 + + name + string.regexp.replace.perl + + 2 + + name + punctuation.definition.string.perl + + 3 + + name + keyword.control.regexp-option.perl + + + patterns + + + begin + (s)\s*\{ + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + \} + name + string.regexp.nested_braces.perl + patterns + + + include + #escaped_char + + + include + #nested_braces + + + + + begin + (s)\s*\[ + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + \] + name + string.regexp.nested_brackets.perl + patterns + + + include + #escaped_char + + + include + #nested_brackets + + + + + begin + (s)\s*< + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + > + name + string.regexp.nested_ltgt.perl + patterns + + + include + #escaped_char + + + include + #nested_ltgt + + + + + begin + (s)\s*\( + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + \) + name + string.regexp.nested_parens.perl + patterns + + + include + #escaped_char + + + include + #nested_parens + + + + + begin + \{ + captures + + 0 + + name + punctuation.definition.string.perl + + + end + \} + name + string.regexp.format.nested_braces.perl + patterns + + + include + #escaped_char + + + include + #variable + + + include + #nested_braces_interpolated + + + + + begin + \[ + captures + + 0 + + name + punctuation.definition.string.perl + + + end + \] + name + string.regexp.format.nested_brackets.perl + patterns + + + include + #escaped_char + + + include + #variable + + + include + #nested_brackets_interpolated + + + + + begin + < + captures + + 0 + + name + punctuation.definition.string.perl + + + end + > + name + string.regexp.format.nested_ltgt.perl + patterns + + + include + #escaped_char + + + include + #variable + + + include + #nested_ltgt_interpolated + + + + + begin + \( + captures + + 0 + + name + punctuation.definition.string.perl + + + end + \) + name + string.regexp.format.nested_parens.perl + patterns + + + include + #escaped_char + + + include + #variable + + + include + #nested_parens_interpolated + + + + + begin + ' + captures + + 0 + + name + punctuation.definition.string.perl + + + end + ' + name + string.regexp.format.single_quote.perl + patterns + + + match + \\['\\] + name + constant.character.escape.perl + + + + + begin + ([^\s\w\[({<;]) + captures + + 0 + + name + punctuation.definition.string.perl + + + end + \1 + name + string.regexp.format.simple_delimiter.perl + patterns + + + include + #escaped_char + + + include + #variable + + + + + match + \s+ + + + + + begin + \b(?=s([^\sa-zA-Z0-9\[({<]).*\1([egimosxradlupc]*)([\}\)\;\,]|\s+)) + comment + string.regexp.replaceXXX + end + ((([egimosxradlupc]*)))(?=([\}\)\;\,]|\s+|$)) + endCaptures + + 1 + + name + string.regexp.replace.perl + + 2 + + name + punctuation.definition.string.perl + + 3 + + name + keyword.control.regexp-option.perl + + + patterns + + + begin + (s\s*)([^\sa-zA-Z0-9\[({<]) + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + (?=\2) + name + string.regexp.replaceXXX.simple_delimiter.perl + patterns + + + include + #escaped_char + + + + + begin + ' + captures + + 0 + + name + punctuation.definition.string.perl + + + end + ' + name + string.regexp.replaceXXX.format.single_quote.perl + patterns + + + match + \\['\\] + name + constant.character.escape.perl.perl + + + + + begin + ([^\sa-zA-Z0-9\[({<]) + captures + + 0 + + name + punctuation.definition.string.perl + + + end + \1 + name + string.regexp.replaceXXX.format.simple_delimiter.perl + patterns + + + include + #escaped_char + + + include + #variable + + + + + + + begin + \b(?=(?<!\\)s\s*([^\s\w\[({<>])) + comment + string.regexp.replace.extended + end + \2((([egimosradlupc]*x[egimosradlupc]*)))\b + endCaptures + + 1 + + name + string.regexp.replace.perl + + 2 + + name + punctuation.definition.string.perl + + 3 + + name + keyword.control.regexp-option.perl + + + patterns + + + begin + (s)\s*(.) + captures + + 0 + + name + punctuation.definition.string.perl + + 1 + + name + support.function.perl + + + end + (?=\2) + name + string.regexp.replace.extended.simple_delimiter.perl + patterns + + + include + #escaped_char + + + + + begin + ' + captures + + 0 + + name + punctuation.definition.string.perl + + + end + '(?=[egimosradlupc]*x[egimosradlupc]*)\b + name + string.regexp.replace.extended.simple_delimiter.perl + patterns + + + include + #escaped_char + + + + + begin + (.) + captures + + 0 + + name + punctuation.definition.string.perl + + + end + \1(?=[egimosradlupc]*x[egimosradlupc]*)\b + name + string.regexp.replace.extended.simple_delimiter.perl + patterns + + + include + #escaped_char + + + include + #variable + + + + + + + begin + (?<=\(|\{|~|&)\s*((\/)) + beginCaptures + + 1 + + name + string.regexp.find.perl + + 2 + + name + punctuation.definition.string.perl + + + contentName + string.regexp.find.perl + end + ((\1([egimosxradlupc]*)))(?=(\s+\S|\s*[;\,\#\{\}\)]|$)) + endCaptures + + 1 + + name + string.regexp.find.perl + + 2 + + name + punctuation.definition.string.perl + + 3 + + name + keyword.control.regexp-option.perl + + + patterns + + + comment + This is to prevent thinks like /foo$/ to treat $/ as a variable + match + \$(?=\/) + name + keyword.control.anchor.perl + + + include + #escaped_char + + + include + #variable + + + + + captures + + 1 + + name + constant.other.key.perl + + + match + \b(\w+)\s*(?==>) + + + match + (?<={)\s*\w+\s*(?=}) + name + constant.other.bareword.perl + + + captures + + 1 + + name + keyword.control.perl + + 2 + + name + entity.name.type.class.perl + + + match + ^\s*(package)\s+([^\s;]+) + name + meta.class.perl + + + captures + + 1 + + name + storage.type.sub.perl + + 2 + + name + entity.name.function.perl + + 3 + + name + storage.type.method.perl + + + match + \b(sub)(?:\s+([-a-zA-Z0-9_]+))?\s*(?:\([\$\@\*;]*\))?[^\w\{] + name + meta.function.perl + + + captures + + 1 + + name + entity.name.function.perl + + 2 + + name + punctuation.definition.parameters.perl + + 3 + + name + variable.parameter.function.perl + + + match + ^\s*(BEGIN|UNITCHECK|CHECK|INIT|END|DESTROY)\b + name + meta.function.perl + + + begin + ^(?=(\t| {4})) + end + (?=[^\t\s]) + name + meta.leading-tabs + patterns + + + captures + + 1 + + name + meta.odd-tab + + 2 + + name + meta.even-tab + + + match + (\t| {4})(\t| {4})? + + + + + captures + + 1 + + name + support.function.perl + + 2 + + name + punctuation.definition.string.perl + + 5 + + name + punctuation.definition.string.perl + + 8 + + name + punctuation.definition.string.perl + + + match + \b(tr|y)\s*([^A-Za-z0-9\s])(.*?)(?<!\\)(\\{2})*(\2)(.*?)(?<!\\)(\\{2})*(\2) + name + string.regexp.replace.perl + + + match + \b(__FILE__|__LINE__|__PACKAGE__|__SUB__|__DATA__|__END__)\b + name + constant.language.perl + + + match + (?<!->)\b(continue|die|do|else|elsif|exit|for|foreach|goto|if|last|next|redo|return|select|unless|until|wait|while|switch|case|require|use|eval)\b + name + keyword.control.perl + + + match + \b(my|our|local)\b + name + storage.modifier.perl + + + match + (?<!\w)\-[rwx0RWXOezsfdlpSbctugkTBMAC]\b + name + keyword.operator.filetest.perl + + + match + \b(and|or|xor|as|not)\b + name + keyword.operator.logical.perl + + + match + (<=>|=>|->) + name + keyword.operator.comparison.perl + + + begin + (((<<) *"HTML"))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.doublequote.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + text.html.embedded.perl + end + (^HTML$) + patterns + + + include + #escaped_char + + + include + #variable + + + include + text.html.basic + + + + + begin + (((<<) *"XML"))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.doublequote.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + text.xml.embedded.perl + end + (^XML$) + patterns + + + include + #escaped_char + + + include + #variable + + + include + text.xml + + + + + begin + (((<<) *"CSS"))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.doublequote.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + text.css.embedded.perl + end + (^CSS$) + patterns + + + include + #escaped_char + + + include + #variable + + + include + source.css + + + + + begin + (((<<) *"JAVASCRIPT"))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.doublequote.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + text.js.embedded.perl + end + (^JAVASCRIPT$) + patterns + + + include + #escaped_char + + + include + #variable + + + include + source.js + + + + + begin + (((<<) *"SQL"))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.doublequote.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + source.sql.embedded.perl + end + (^SQL$) + patterns + + + include + #escaped_char + + + include + #variable + + + include + source.sql + + + + + begin + (((<<) *"POSTSCRIPT"))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.doublequote.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + text.postscript.embedded.perl + end + (^POSTSCRIPT$) + patterns + + + include + #escaped_char + + + include + #variable + + + include + source.postscript + + + + + begin + (((<<) *"([^"]*)"))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.doublequote.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + string.unquoted.heredoc.doublequote.perl + end + (^\4$) + patterns + + + include + #escaped_char + + + include + #variable + + + + + begin + (((<<) *'HTML'))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.quote.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + text.html.embedded.perl + end + (^HTML$) + patterns + + + include + text.html.basic + + + + + begin + (((<<) *'XML'))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.quote.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + text.xml.embedded.perl + end + (^XML$) + patterns + + + include + text.xml + + + + + begin + (((<<) *'CSS'))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.quote.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + text.css.embedded.perl + end + (^CSS$) + patterns + + + include + source.css + + + + + begin + (((<<) *'JAVASCRIPT'))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.quote.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + text.js.embedded.perl + end + (^JAVASCRIPT$) + patterns + + + include + source.js + + + + + begin + (((<<) *'SQL'))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.quote.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + source.sql.embedded.perl + end + (^SQL$) + patterns + + + include + source.sql + + + + + begin + (((<<) *'POSTSCRIPT'))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.quote.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + source.postscript.embedded.perl + end + (^POSTSCRIPT$) + patterns + + + include + source.postscript + + + + + begin + (((<<) *'([^']*)'))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.quote.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + string.unquoted.heredoc.quote.perl + end + (^\4$) + + + begin + (((<<) *\\((?![=\d\$\( ])[^;,'"`\s\)]*)))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.quote.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + string.unquoted.heredoc.quote.perl + end + (^\4$) + + + begin + (((<<) *`([^`]*)`))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.backtick.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + string.unquoted.heredoc.backtick.perl + end + (^\4$) + patterns + + + include + #escaped_char + + + include + #variable + + + + + begin + (((<<) *HTML\b))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + text.html.embedded.perl + end + (^HTML$) + patterns + + + include + #escaped_char + + + include + #variable + + + include + text.html.basic + + + + + begin + (((<<) *XML\b))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + text.xml.embedded.perl + end + (^XML$) + patterns + + + include + #escaped_char + + + include + #variable + + + include + text.xml + + + + + begin + (((<<) *JAVASCRIPT\b))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + source.js.embedded.perl + end + (^JAVASCRIPT$) + patterns + + + include + #escaped_char + + + include + #variable + + + include + source.js + + + + + begin + (((<<) *SQL\b))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + source.sql.embedded.perl + end + (^SQL$) + patterns + + + include + #escaped_char + + + include + #variable + + + include + source.sql + + + + + begin + (((<<) *POSTSCRIPT\b))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 4 + + patterns + + + include + $self + + + + + contentName + source.postscript.embedded.perl + end + (^POSTSCRIPT$) + patterns + + + include + #escaped_char + + + include + #variable + + + include + source.postscript + + + + + begin + (((<<) *((?![=\d\$\( ])[^;,'"`\s\)]*)))(.*)\n? + captures + + 1 + + name + punctuation.definition.string.perl + + 2 + + name + string.unquoted.heredoc.perl + + 3 + + name + punctuation.definition.heredoc.perl + + 5 + + patterns + + + include + $self + + + + + contentName + string.unquoted.heredoc.perl + end + (^\4$) + patterns + + + include + #escaped_char + + + include + #variable + + + + + begin + \bqq\s*([^\(\{\[\<\w\s]) + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + \1 + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.quoted.other.qq.perl + patterns + + + include + #escaped_char + + + include + #variable + + + + + begin + \bqx\s*([^'\(\{\[\<\w\s]) + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + \1 + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.interpolated.qx.perl + patterns + + + include + #escaped_char + + + include + #variable + + + + + begin + \bqx\s*' + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + ' + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.interpolated.qx.single-quote.perl + patterns + + + include + #escaped_char + + + + + begin + " + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + " + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.quoted.double.perl + patterns + + + include + #escaped_char + + + include + #variable + + + + + begin + (?<!->)\bqw?\s*([^\(\{\[\<\w\s]) + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + \1 + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.quoted.other.q.perl + + + begin + ' + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + ' + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.quoted.single.perl + patterns + + + match + \\['\\] + name + constant.character.escape.perl + + + + + begin + ` + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + ` + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.interpolated.perl + patterns + + + include + #escaped_char + + + include + #variable + + + + + begin + (?<!->)\bqq\s*\( + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + \) + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.quoted.other.qq-paren.perl + patterns + + + include + #escaped_char + + + include + #nested_parens_interpolated + + + include + #variable + + + + + begin + \bqq\s*\{ + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + \} + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.quoted.other.qq-brace.perl + patterns + + + include + #escaped_char + + + include + #nested_braces_interpolated + + + include + #variable + + + + + begin + \bqq\s*\[ + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + \] + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.quoted.other.qq-bracket.perl + patterns + + + include + #escaped_char + + + include + #nested_brackets_interpolated + + + include + #variable + + + + + begin + \bqq\s*\< + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + \> + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.quoted.other.qq-ltgt.perl + patterns + + + include + #escaped_char + + + include + #nested_ltgt_interpolated + + + include + #variable + + + + + begin + (?<!->)\bqx\s*\( + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + \) + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.interpolated.qx-paren.perl + patterns + + + include + #escaped_char + + + include + #nested_parens_interpolated + + + include + #variable + + + + + begin + \bqx\s*\{ + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + \} + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.interpolated.qx-brace.perl + patterns + + + include + #escaped_char + + + include + #nested_braces_interpolated + + + include + #variable + + + + + begin + \bqx\s*\[ + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + \] + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.interpolated.qx-bracket.perl + patterns + + + include + #escaped_char + + + include + #nested_brackets_interpolated + + + include + #variable + + + + + begin + \bqx\s*\< + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + \> + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.interpolated.qx-ltgt.perl + patterns + + + include + #escaped_char + + + include + #nested_ltgt_interpolated + + + include + #variable + + + + + begin + (?<!->)\bqw?\s*\( + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + \) + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.quoted.other.q-paren.perl + patterns + + + include + #nested_parens + + + + + begin + \bqw?\s*\{ + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + \} + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.quoted.other.q-brace.perl + patterns + + + include + #nested_braces + + + + + begin + \bqw?\s*\[ + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + \] + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.quoted.other.q-bracket.perl + patterns + + + include + #nested_brackets + + + + + begin + \bqw?\s*\< + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + \> + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.quoted.other.q-ltgt.perl + patterns + + + include + #nested_ltgt + + + + + begin + ^__\w+__ + beginCaptures + + 0 + + name + punctuation.definition.string.begin.perl + + + end + $ + endCaptures + + 0 + + name + punctuation.definition.string.end.perl + + + name + string.unquoted.program-block.perl + + + begin + \b(format)\s+(\w+)\s*= + beginCaptures + + 1 + + name + support.function.perl + + 2 + + name + entity.name.function.format.perl + + + end + ^\.\s*$ + name + meta.format.perl + patterns + + + include + #line_comment + + + include + #variable + + + + + captures + + 1 + + name + support.function.perl + + 2 + + name + entity.name.function.perl + + + match + \b(x)\s*(\d+)\b + + + match + \b(ARGV|DATA|ENV|SIG|STDERR|STDIN|STDOUT|atan2|bind|binmode|bless|caller|chdir|chmod|chomp|chop|chown|chr|chroot|close|closedir|cmp|connect|cos|crypt|dbmclose|dbmopen|defined|delete|dump|each|endgrent|endhostent|endnetent|endprotoent|endpwent|endservent|eof|eq|eval|exec|exists|exp|fcntl|fileno|flock|fork|formline|ge|getc|getgrent|getgrgid|getgrnam|gethostbyaddr|gethostbyname|gethostent|getlogin|getnetbyaddr|getnetbyname|getnetent|getpeername|getpgrp|getppid|getpriority|getprotobyname|getprotobynumber|getprotoent|getpwent|getpwnam|getpwuid|getservbyname|getservbyport|getservent|getsockname|getsockopt|glob|gmtime|grep|gt|hex|import|index|int|ioctl|join|keys|kill|lc|lcfirst|le|length|link|listen|local|localtime|log|lstat|lt|m|map|mkdir|msgctl|msgget|msgrcv|msgsnd|ne|no|oct|open|opendir|ord|pack|pipe|pop|pos|print|printf|push|quotemeta|rand|read|readdir|readlink|recv|ref|rename|reset|reverse|rewinddir|rindex|rmdir|s|scalar|seek|seekdir|semctl|semget|semop|send|setgrent|sethostent|setnetent|setpgrp|setpriority|setprotoent|setpwent|setservent|setsockopt|shift|shmctl|shmget|shmread|shmwrite|shutdown|sin|sleep|socket|socketpair|sort|splice|split|sprintf|sqrt|srand|stat|study|substr|symlink|syscall|sysopen|sysread|system|syswrite|tell|telldir|tie|tied|time|times|tr|truncate|uc|ucfirst|umask|undef|unlink|unpack|unshift|untie|utime|values|vec|waitpid|wantarray|warn|write|y)\b + name + support.function.perl + + + captures + + 1 + + name + punctuation.section.scope.begin.perl + + 2 + + name + punctuation.section.scope.end.perl + + + comment + Match empty brackets for ↩ snippet + match + (\{)(\}) + + + captures + + 1 + + name + punctuation.section.scope.begin.perl + + 2 + + name + punctuation.section.scope.end.perl + + + comment + Match empty parenthesis for ↩ snippet + match + (\()(\)) + + + repository + + escaped_char + + patterns + + + match + \\\d+ + name + constant.character.escape.perl + + + match + \\c[^\s\\] + name + constant.character.escape.perl + + + match + \\g(?:\{(?:\w*|-\d+)\}|\d+) + name + constant.character.escape.perl + + + match + \\k(?:\{\w*\}|<\w*>|'\w*') + name + constant.character.escape.perl + + + match + \\N\{[^\}]*\} + name + constant.character.escape.perl + + + match + \\o\{\d*\} + name + constant.character.escape.perl + + + match + \\(?:p|P)(?:\{\w*\}|P) + name + constant.character.escape.perl + + + match + \\x(?:[0-9a-zA-Z]{2}|\{\w*\})? + name + constant.character.escape.perl + + + match + \\. + name + constant.character.escape.perl + + + + line_comment + + patterns + + + begin + (^[ \t]+)?(?=#) + beginCaptures + + 1 + + name + punctuation.whitespace.comment.leading.perl + + + end + (?!\G) + patterns + + + begin + # + beginCaptures + + 0 + + name + punctuation.definition.comment.perl + + + end + \n + name + comment.line.number-sign.perl + + + + + + nested_braces + + begin + \{ + captures + + 1 + + name + punctuation.section.scope.perl + + + end + \} + patterns + + + include + #escaped_char + + + include + #nested_braces + + + + nested_braces_interpolated + + begin + \{ + captures + + 1 + + name + punctuation.section.scope.perl + + + end + \} + patterns + + + include + #escaped_char + + + include + #variable + + + include + #nested_braces_interpolated + + + + nested_brackets + + begin + \[ + captures + + 1 + + name + punctuation.section.scope.perl + + + end + \] + patterns + + + include + #escaped_char + + + include + #nested_brackets + + + + nested_brackets_interpolated + + begin + \[ + captures + + 1 + + name + punctuation.section.scope.perl + + + end + \] + patterns + + + include + #escaped_char + + + include + #variable + + + include + #nested_brackets_interpolated + + + + nested_ltgt + + begin + < + captures + + 1 + + name + punctuation.section.scope.perl + + + end + > + patterns + + + include + #nested_ltgt + + + + nested_ltgt_interpolated + + begin + < + captures + + 1 + + name + punctuation.section.scope.perl + + + end + > + patterns + + + include + #variable + + + include + #nested_ltgt_interpolated + + + + nested_parens + + begin + \( + captures + + 1 + + name + punctuation.section.scope.perl + + + end + \) + patterns + + + include + #escaped_char + + + include + #nested_parens + + + + nested_parens_interpolated + + begin + \( + captures + + 1 + + name + punctuation.section.scope.perl + + + end + \) + patterns + + + comment + This is to prevent thinks like qr/foo$/ to treat $/ as a variable + match + \$(?=[^\s\w'\{\[\(\<]) + name + keyword.control.anchor.perl + + + include + #escaped_char + + + include + #variable + + + include + #nested_parens_interpolated + + + + variable + + patterns + + + captures + + 1 + + name + punctuation.definition.variable.perl + + + match + (\$)&(?![A-Za-z0-9_]) + name + variable.other.regexp.match.perl + + + captures + + 1 + + name + punctuation.definition.variable.perl + + + match + (\$)`(?![A-Za-z0-9_]) + name + variable.other.regexp.pre-match.perl + + + captures + + 1 + + name + punctuation.definition.variable.perl + + + match + (\$)'(?![A-Za-z0-9_]) + name + variable.other.regexp.post-match.perl + + + captures + + 1 + + name + punctuation.definition.variable.perl + + + match + (\$)\+(?![A-Za-z0-9_]) + name + variable.other.regexp.last-paren-match.perl + + + captures + + 1 + + name + punctuation.definition.variable.perl + + + match + (\$)"(?![A-Za-z0-9_]) + name + variable.other.readwrite.list-separator.perl + + + captures + + 1 + + name + punctuation.definition.variable.perl + + + match + (\$)0(?![A-Za-z0-9_]) + name + variable.other.predefined.program-name.perl + + + captures + + 1 + + name + punctuation.definition.variable.perl + + + match + (\$)[_ab\*\.\/\|,\\;#%=\-~^:?!\$<>\(\)\[\]@](?![A-Za-z0-9_]) + name + variable.other.predefined.perl + + + captures + + 1 + + name + punctuation.definition.variable.perl + + + match + (\$)[0-9]+(?![A-Za-z0-9_]) + name + variable.other.subpattern.perl + + + captures + + 1 + + name + punctuation.definition.variable.perl + + + match + ([\$\@\%](#)?)([a-zA-Zx7f-xff\$]|::)([a-zA-Z0-9_x7f-xff\$]|::)*\b + name + variable.other.readwrite.global.perl + + + captures + + 1 + + name + punctuation.definition.variable.perl + + 2 + + name + punctuation.definition.variable.perl + + + match + (\$\{)(?:[a-zA-Zx7f-xff\$]|::)(?:[a-zA-Z0-9_x7f-xff\$]|::)*(\}) + name + variable.other.readwrite.global.perl + + + captures + + 1 + + name + punctuation.definition.variable.perl + + + match + ([\$\@\%](#)?)[0-9_]\b + name + variable.other.readwrite.global.special.perl + + + + + scopeName + source.perl + uuid + EDBFE125-6B1C-11D9-9189-000D93589AF6 + \ No newline at end of file diff --git a/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Pug.tmLanguage b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Pug.tmLanguage new file mode 100644 index 000000000..164026d31 --- /dev/null +++ b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Pug.tmLanguage @@ -0,0 +1,1486 @@ + + + + + fileTypes + + pug + + name + Pug + patterns + + + comment + Doctype declaration. + match + ^(!!!|doctype)(\s*[a-zA-Z0-9-_]+)? + name + meta.tag.sgml.doctype.html + + + begin + ^(\s*)//- + comment + Unbuffered (pug-only) comments. + end + ^(?!(\1\s)|\s*$) + name + comment.unbuffered.block.pug + + + begin + ^(\s*)// + comment + Buffered (html) comments. + end + ^(?!(\1\s)|\s*$) + name + string.comment.buffered.block.pug + patterns + + + captures + + 1 + + name + invalid.illegal.comment.comment.block.pug + + + comment + Buffered comments inside buffered comments will generate invalid html. + match + ^\s*(//)(?!-) + name + string.comment.buffered.block.pug + + + + + begin + <!-- + end + --\s*> + name + comment.unbuffered.block.pug + patterns + + + match + -- + name + invalid.illegal.comment.comment.block.pug + + + + + begin + ^(\s*)-$ + comment + Unbuffered code block. + end + ^(?!(\1\s)|\s*$) + name + source.js + patterns + + + include + source.js + + + + + begin + ^(\s*)(script)((\.$)|(?=[^\n]*(text|application)/javascript.*\.$)) + beginCaptures + + 2 + + name + entity.name.tag.pug + + + comment + Script tag with JavaScript code. + end + ^(?!(\1\s)|\s*$) + name + meta.tag.other + patterns + + + begin + \G(?=\() + end + $ + patterns + + + include + #tag_attributes + + + + + begin + \G(?=[.#]) + end + $ + patterns + + + include + #complete_tag + + + + + include + source.js + + + + + begin + ^(\s*)(style)((\.$)|(?=[.#(].*\.$)) + beginCaptures + + 2 + + name + entity.name.tag.pug + + + comment + Style tag with CSS code. + end + ^(?!(\1\s)|\s*$) + name + meta.tag.other + patterns + + + begin + \G(?=\() + end + $ + patterns + + + include + #tag_attributes + + + + + begin + \G(?=[.#]) + end + $ + patterns + + + include + #complete_tag + + + + + include + source.css + + + + + begin + ^(\s*):(sass)(?=\(|$) + beginCaptures + + 2 + + name + constant.language.name.sass.filter.pug + + + end + ^(?!(\1\s)|\s*$) + name + source.sass.filter.pug + patterns + + + include + #tag_attributes + + + include + source.sass + + + + + begin + ^(\s*):(less)(?=\(|$) + beginCaptures + + 2 + + name + constant.language.name.less.filter.pug + + + end + ^(?!(\1\s)|\s*$) + name + source.less.filter.pug + patterns + + + include + #tag_attributes + + + include + source.less + + + + + begin + ^(\s*):(stylus)(?=\(|$) + beginCaptures + + 2 + + name + constant.language.name.stylus.filter.pug + + + end + ^(?!(\1\s)|\s*$) + patterns + + + include + #tag_attributes + + + include + source.stylus + + + + + begin + ^(\s*):(coffee(-?script)?)(?=\(|$) + beginCaptures + + 2 + + name + constant.language.name.coffeescript.filter.pug + + + end + ^(?!(\1\s)|\s*$) + name + source.coffeescript.filter.pug + patterns + + + include + #tag_attributes + + + include + source.coffee + + + + + begin + ^(\s*)((:(?=.))|(:$)) + beginCaptures + + 4 + + name + invalid.illegal.empty.generic.filter.pug + + + comment + Generic Pug filter. + end + ^(?!(\1\s)|\s*$) + patterns + + + begin + \G(?<=:)(?=.) + end + $ + name + name.generic.filter.pug + patterns + + + match + \G\( + name + invalid.illegal.name.generic.filter.pug + + + match + [\w-] + name + constant.language.name.generic.filter.pug + + + include + #tag_attributes + + + match + \W + name + invalid.illegal.name.generic.filter.pug + + + + + + + begin + ^(\s*)(?=[\w.#].*?\.$)(?=(?:(?:(?:(?:(?:#[\w-]+)|(?:\.[\w-]+))|(?:(?:[#!]\{[^}]*\})|(?:\w(?:(?:[\w:-]+[\w-])|(?:[\w-]*)))))(?:(?:#[\w-]+)|(?:\.[\w-]+)|(?:\((?:[^()\'\"]*(?:(?:\'(?:[^\']|(?:(?<!\\)\\\'))*\')|(?:\"(?:[^\"]|(?:(?<!\\)\\\"))*\")))*[^()]*\))*)*)(?:(?:(?::\s+)|(?<=\)))(?:(?:(?:(?:#[\w-]+)|(?:\.[\w-]+))|(?:(?:[#!]\{[^}]*\})|(?:\w(?:(?:[\w:-]+[\w-])|(?:[\w-]*)))))(?:(?:#[\w-]+)|(?:\.[\w-]+)|(?:\((?:[^()\'\"]*(?:(?:\'(?:[^\']|(?:(?<!\\)\\\'))*\')|(?:\"(?:[^\"]|(?:(?<!\\)\\\"))*\")))*[^()]*\))*)*))*)\.$)(?:(?:(#[\w-]+)|(\.[\w-]+))|((?:[#!]\{[^}]*\})|(?:\w(?:(?:[\w:-]+[\w-])|(?:[\w-]*))))) + beginCaptures + + 2 + + name + entity.other.attribute-name.id.pug + + 3 + + name + entity.other.attribute-name.class.pug + + 4 + + name + meta.tag.other entity.name.tag.pug + + + comment + Generated from dot_block_tag.py + end + ^(?!(\1\s)|\s*$) + patterns + + + include + #tag_attributes + + + include + #complete_tag + + + begin + ^(?=.) + end + $ + name + text.block.pug + patterns + + + include + #inline_pug + + + include + #embedded_html + + + include + #html_entity + + + include + #interpolated_value + + + include + #interpolated_error + + + + + + + begin + ^\s* + comment + All constructs that generally span a single line starting with any number of white-spaces. + end + $ + patterns + + + include + #inline_pug + + + include + #blocks_and_includes + + + include + #unbuffered_code + + + include + #mixin_definition + + + include + #mixin_call + + + include + #flow_control + + + include + #case_conds + + + begin + \| + comment + Tag pipe text line. + end + $ + name + text.block.pipe.pug + patterns + + + include + #inline_pug + + + include + #embedded_html + + + include + #html_entity + + + include + #interpolated_value + + + include + #interpolated_error + + + + + include + #printed_expression + + + begin + \G(?=(#[^\{\w-])|[^\w.#]) + comment + Line starting with characters incompatible with tag name/id/class is standalone text. + end + $ + patterns + + + begin + </?(?=[!#]) + end + >|$ + patterns + + + include + #inline_pug + + + include + #interpolated_value + + + include + #interpolated_error + + + + + include + #inline_pug + + + include + #embedded_html + + + include + #html_entity + + + include + #interpolated_value + + + include + #interpolated_error + + + + + include + #complete_tag + + + + + repository + + babel_parens + + begin + \( + end + \)|(({\s*)?$) + patterns + + + include + #babel_parens + + + include + source.js + + + + blocks_and_includes + + captures + + 1 + + name + storage.type.import.include.pug + + 4 + + name + variable.control.import.include.pug + + + comment + Template blocks and includes. + match + (extends|include|yield|append|prepend|block( (append|prepend))?)\s+(.*)$ + name + meta.first-class.pug + + case_conds + + begin + (default|when)((\s+|(?=:))|$) + captures + + 1 + + name + storage.type.function.pug + + + comment + Pug case conditionals. + end + $ + name + meta.control.flow.pug + patterns + + + begin + \G(?!:) + end + (?=:\s+)|$ + name + js.embedded.control.flow.pug + patterns + + + include + #case_when_paren + + + include + source.js + + + + + begin + :\s+ + end + $ + name + tag.case.control.flow.pug + patterns + + + include + #complete_tag + + + + + + case_when_paren + + begin + \( + end + \) + name + js.when.control.flow.pug + patterns + + + include + #case_when_paren + + + match + : + name + invalid.illegal.name.tag.pug + + + include + source.js + + + + complete_tag + + begin + (?=[\w.#])|(:\s*) + end + (\.?$)|(?=:.) + patterns + + + include + #blocks_and_includes + + + include + #unbuffered_code + + + include + #mixin_call + + + include + #flow_control + + + match + (?<=:)\w.*$ + name + invalid.illegal.name.tag.pug + + + include + #tag_name + + + include + #tag_id + + + include + #tag_classes + + + include + #tag_attributes + + + include + #tag_mixin_attributes + + + captures + + 2 + + name + invalid.illegal.end.tag.pug + + 4 + + name + invalid.illegal.end.tag.pug + + + match + ((\.)\s+$)|((:)\s*$) + + + include + #printed_expression + + + include + #tag_text + + + + embedded_html + + begin + (?=<[^>]*>) + end + $|(?=>) + name + html + patterns + + + include + text.html.basic + + + include + #interpolated_value + + + include + #interpolated_error + + + + flow_control + + begin + (for|if|else if|else|each|until|while|unless|case)(\s+|$) + captures + + 1 + + name + storage.type.function.pug + + + comment + Pug control flow. + end + $ + name + meta.control.flow.pug + patterns + + + begin + + end + $ + name + js.embedded.control.flow.pug + patterns + + + include + source.js + + + + + + html_entity + + patterns + + + match + (&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;) + name + constant.character.entity.html.text.pug + + + match + [<>&] + name + invalid.illegal.html_entity.text.pug + + + + inline_pug + + begin + (?<!\\)(#\[) + captures + + 1 + + name + entity.name.function.pug + + 2 + + name + entity.name.function.pug + + + end + (\]) + name + inline.pug + patterns + + + include + #inline_pug + + + include + #mixin_call + + + begin + (?<!\])(?=[\w.#])|(:\s*) + end + (?=\]|(:.)|=|\s) + name + tag.inline.pug + patterns + + + include + #tag_name + + + include + #tag_id + + + include + #tag_classes + + + include + #tag_attributes + + + include + #tag_mixin_attributes + + + include + #inline_pug + + + match + \[ + name + invalid.illegal.tag.pug + + + + + include + #unbuffered_code + + + include + #printed_expression + + + match + \[ + name + invalid.illegal.tag.pug + + + include + #inline_pug_text + + + + inline_pug_text + + begin + + end + (?=\]) + patterns + + + begin + \[ + end + \] + patterns + + + include + #inline_pug_text + + + + + include + #inline_pug + + + include + #embedded_html + + + include + #html_entity + + + include + #interpolated_value + + + include + #interpolated_error + + + + interpolated_error + + match + (?<!\\)[#!]\{(?=[^}]*$) + name + invalid.illegal.tag.pug + + interpolated_value + + begin + (?<!\\)[#!]\{(?=.*?\}) + end + \} + name + string.interpolated.pug + patterns + + + match + { + name + invalid.illegal.tag.pug + + + include + source.js + + + + js_braces + + begin + \{ + end + \} + patterns + + + include + #js_braces + + + include + source.js + + + + js_brackets + + begin + \[ + end + \] + patterns + + + include + #js_brackets + + + include + source.js + + + + js_parens + + begin + \( + end + \) + patterns + + + include + #js_parens + + + include + source.js + + + + mixin_call + + begin + ((?:mixin\s+)|\+)([\w-]+) + beginCaptures + + 1 + + name + storage.type.function.pug + + 2 + + name + meta.tag.other entity.name.function.pug + + + end + (?!\()|$ + patterns + + + begin + (?<!\))\( + end + \) + name + args.mixin.pug + patterns + + + include + #js_parens + + + include + #string + + + captures + + 1 + + name + meta.tag.other entity.other.attribute-name.tag.pug + + + match + ([^\s(),=/]+)\s*=\s* + + + include + source.js + + + + + include + #tag_attributes + + + + mixin_definition + + captures + + 1 + + name + storage.type.function.pug + + 2 + + name + meta.tag.other entity.name.function.pug + + 3 + + name + punctuation.definition.parameters.begin.js + + 4 + + name + variable.parameter.function.js + + 5 + + name + punctuation.definition.parameters.begin.js + + + match + (mixin\s+)([\w-]+)(?:(\()\s*((?:[a-zA-Z_]\w*\s*)(?:,\s*[a-zA-Z_]\w*\s*)*)(\)))?$ + + printed_expression + + begin + (!?\=)\s* + captures + + 1 + + name + constant + + + end + (?=\])|$ + name + source.js + patterns + + + include + #js_brackets + + + include + source.js + + + + string + + begin + (['"]) + end + (?<!\\)\1 + name + string.quoted.pug + patterns + + + match + \\((x[0-9a-fA-F]{2})|(u[0-9]{4})|.) + name + constant.character.quoted.pug + + + include + #interpolated_value + + + include + #interpolated_error + + + + tag_attribute_name + + captures + + 1 + + name + entity.other.attribute-name.tag.pug + + + match + ([^\s(),=/!]+)\s* + + tag_attribute_name_paren + + begin + \(\s* + end + \) + name + entity.other.attribute-name.tag.pug + patterns + + + include + #tag_attribute_name_paren + + + include + #tag_attribute_name + + + + tag_attributes + + begin + (\(\s*) + captures + + 1 + + name + constant.name.attribute.tag.pug + + + end + (\)) + name + meta.tag.other + patterns + + + include + #tag_attribute_name_paren + + + include + #tag_attribute_name + + + match + !(?!=) + name + invalid.illegal.tag.pug + + + begin + =\s* + end + $|(?=,|(?:\s+[^!%&*-+~|<>:?/])|\)) + name + attribute_value + patterns + + + include + #string + + + include + #js_parens + + + include + #js_brackets + + + include + #js_braces + + + include + source.js + + + + + begin + (?<=[%&*-+~|<>:?/])\s+ + end + $|(?=,|(?:\s+[^!%&*-+~|<>:?/])|\)) + name + attribute_value2 + patterns + + + include + #string + + + include + #js_parens + + + include + #js_brackets + + + include + #js_braces + + + include + source.js + + + + + + tag_classes + + captures + + 1 + + name + invalid.illegal.tag.pug + + + match + \.([^\w-])?[\w-]* + name + entity.other.attribute-name.class.pug + + tag_id + + match + #[\w-]+ + name + entity.other.attribute-name.id.pug + + tag_mixin_attributes + + begin + (&attributes\() + captures + + 1 + + name + entity.name.function.pug + + + end + (\)) + name + meta.tag.other + patterns + + + match + attributes(?=\)) + name + storage.type.keyword.pug + + + include + source.js + + + + tag_name + + begin + ([#!]\{(?=.*?\}))|(\w(([\w:-]+[\w-])|([\w-]*))) + end + (\G(?<!\5[^\w-]))|\}|$ + name + meta.tag.other entity.name.tag.pug + patterns + + + begin + \G(?<=\{) + end + (?=\}) + name + meta.tag.other entity.name.tag.pug + patterns + + + match + { + name + invalid.illegal.tag.pug + + + include + source.js + + + + + + tag_text + + begin + (?=.) + end + $ + patterns + + + include + #inline_pug + + + include + #embedded_html + + + include + #html_entity + + + include + #interpolated_value + + + include + #interpolated_error + + + + unbuffered_code + + begin + (-|(([a-zA-Z0-9_]+)\s+=)) + beginCaptures + + 3 + + name + variable.parameter.javascript.embedded.pug + + + comment + name = function() {} + end + (?=\])|(({\s*)?$) + name + source.js + patterns + + + include + #js_brackets + + + include + #babel_parens + + + include + source.js + + + + + scopeName + text.pug + uuid + eee6ba25-6ac2-4f7e-9c70-cddf2bd3448b + + \ No newline at end of file diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/Ruby.plist b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Ruby.plist similarity index 99% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/Ruby.plist rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Ruby.plist index fd18e0930..053a01300 100644 --- a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/Ruby.plist +++ b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/Ruby.plist @@ -380,7 +380,7 @@ ( (?>[a-zA-Z_]\w*(?>\.|::))? # a method name prefix (?>[a-zA-Z_]\w*(?>[?!]|=(?!>))? # the method name |===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\]=?) ) # …or an operator method - \s*(\() # the openning parenthesis for arguments + \s*(\() # the opening parenthesis for arguments beginCaptures diff --git a/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/YAML.tmLanguage b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/YAML.tmLanguage new file mode 100644 index 000000000..4a1b7b15b --- /dev/null +++ b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/YAML.tmLanguage @@ -0,0 +1,1164 @@ + + + + + fileTypes + + yaml + yml + rviz + reek + clang-format + yaml-tmlanguage + syntax + sublime-syntax + + firstLineMatch + ^%YAML( ?1.\d+)? + keyEquivalent + ^~Y + name + YAML + patterns + + + include + #comment + + + include + #property + + + include + #directive + + + match + ^--- + name + entity.other.document.begin.yaml + + + match + ^\.{3} + name + entity.other.document.end.yaml + + + include + #node + + + repository + + block-collection + + patterns + + + include + #block-sequence + + + include + #block-mapping + + + + block-mapping + + patterns + + + include + #block-pair + + + + block-node + + patterns + + + include + #prototype + + + include + #block-scalar + + + include + #block-collection + + + include + #flow-scalar-plain-out + + + include + #flow-node + + + + block-pair + + patterns + + + begin + \? + beginCaptures + + 1 + + name + punctuation.definition.key-value.begin.yaml + + + end + (?=\?)|^ *(:)|(:) + endCaptures + + 1 + + name + punctuation.separator.key-value.mapping.yaml + + 2 + + name + invalid.illegal.expected-newline.yaml + + + name + meta.block-mapping.yaml + patterns + + + include + #block-node + + + + + begin + (?x) + (?= + (?x: + [^\s[-?:,\[\]{}#&*!|>'"%@`]] + | [?:-] \S + ) + ( + [^\s:] + | : \S + | \s+ (?![#\s]) + )* + \s* + : + (\s|$) + ) + + end + (?x) + (?= + \s* $ + | \s+ \# + | \s* : (\s|$) + ) + + patterns + + + include + #flow-scalar-plain-out-implicit-type + + + begin + (?x) + [^\s[-?:,\[\]{}#&*!|>'"%@`]] + | [?:-] \S + + beginCaptures + + 0 + + name + entity.name.tag.yaml + + + contentName + entity.name.tag.yaml + end + (?x) + (?= + \s* $ + | \s+ \# + | \s* : (\s|$) + ) + + name + string.unquoted.plain.out.yaml + + + + + match + :(?=\s|$) + name + punctuation.separator.key-value.mapping.yaml + + + + block-scalar + + begin + (?:(\|)|(>))([1-9])?([-+])?(.*\n?) + beginCaptures + + 1 + + name + keyword.control.flow.block-scalar.literal.yaml + + 2 + + name + keyword.control.flow.block-scalar.folded.yaml + + 3 + + name + constant.numeric.indentation-indicator.yaml + + 4 + + name + storage.modifier.chomping-indicator.yaml + + 5 + + patterns + + + include + #comment + + + match + .+ + name + invalid.illegal.expected-comment-or-newline.yaml + + + + + end + ^(?=\S)|(?!\G) + patterns + + + begin + ^([ ]+)(?! ) + end + ^(?!\1|\s*$) + name + string.unquoted.block.yaml + + + + block-sequence + + match + (-)(?!\S) + name + punctuation.definition.block.sequence.item.yaml + + comment + + begin + (?:(^[ \t]*)|[ \t]+)(?=#\p{Print}*$) + beginCaptures + + 1 + + name + punctuation.whitespace.comment.leading.yaml + + + end + (?!\G) + patterns + + + begin + # + beginCaptures + + 0 + + name + punctuation.definition.comment.yaml + + + end + \n + name + comment.line.number-sign.yaml + + + + directive + + begin + ^% + beginCaptures + + 0 + + name + punctuation.definition.directive.begin.yaml + + + end + (?=$|[ \t]+($|#)) + name + meta.directive.yaml + patterns + + + captures + + 1 + + name + keyword.other.directive.yaml.yaml + + 2 + + name + constant.numeric.yaml-version.yaml + + + match + \G(YAML)[ \t]+(\d+\.\d+) + + + captures + + 1 + + name + keyword.other.directive.tag.yaml + + 2 + + name + storage.type.tag-handle.yaml + + 3 + + name + support.type.tag-prefix.yaml + + + match + (?x) + \G + (TAG) + (?:[ \t]+ + ((?:!(?:[0-9A-Za-z\-]*!)?)) + (?:[ \t]+ ( + ! (?x: %[0-9A-Fa-f]{2} | [0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]] )* + | (?![,!\[\]{}]) (?x: %[0-9A-Fa-f]{2} | [0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]] )+ + ) + )? + )? + + + + captures + + 1 + + name + support.other.directive.reserved.yaml + + 2 + + name + string.unquoted.directive-name.yaml + + 3 + + name + string.unquoted.directive-parameter.yaml + + + match + (?x) \G (\w+) (?:[ \t]+ (\w+) (?:[ \t]+ (\w+))? )? + + + match + \S+ + name + invalid.illegal.unrecognized.yaml + + + + flow-alias + + captures + + 1 + + name + keyword.control.flow.alias.yaml + + 2 + + name + punctuation.definition.alias.yaml + + 3 + + name + variable.other.alias.yaml + + 4 + + name + invalid.illegal.character.anchor.yaml + + + match + ((\*))([^\s\[\]/{/},]+)([^\s\]},]\S*)? + + flow-collection + + patterns + + + include + #flow-sequence + + + include + #flow-mapping + + + + flow-mapping + + begin + \{ + beginCaptures + + 0 + + name + punctuation.definition.mapping.begin.yaml + + + end + \} + endCaptures + + 0 + + name + punctuation.definition.mapping.end.yaml + + + name + meta.flow-mapping.yaml + patterns + + + include + #prototype + + + match + , + name + punctuation.separator.mapping.yaml + + + include + #flow-pair + + + + flow-node + + patterns + + + include + #prototype + + + include + #flow-alias + + + include + #flow-collection + + + include + #flow-scalar + + + + flow-pair + + patterns + + + begin + \? + beginCaptures + + 0 + + name + punctuation.definition.key-value.begin.yaml + + + end + (?=[},\]]) + name + meta.flow-pair.explicit.yaml + patterns + + + include + #prototype + + + include + #flow-pair + + + include + #flow-node + + + begin + :(?=\s|$|[\[\]{},]) + beginCaptures + + 0 + + name + punctuation.separator.key-value.mapping.yaml + + + end + (?=[},\]]) + patterns + + + include + #flow-value + + + + + + + begin + (?x) + (?= + (?: + [^\s[-?:,\[\]{}#&*!|>'"%@`]] + | [?:-] [^\s[\[\]{},]] + ) + ( + [^\s:[\[\]{},]] + | : [^\s[\[\]{},]] + | \s+ (?![#\s]) + )* + \s* + : + (\s|$) + ) + + end + (?x) + (?= + \s* $ + | \s+ \# + | \s* : (\s|$) + | \s* : [\[\]{},] + | \s* [\[\]{},] + ) + + name + meta.flow-pair.key.yaml + patterns + + + include + #flow-scalar-plain-in-implicit-type + + + begin + (?x) + [^\s[-?:,\[\]{}#&*!|>'"%@`]] + | [?:-] [^\s[\[\]{},]] + + beginCaptures + + 0 + + name + entity.name.tag.yaml + + + contentName + entity.name.tag.yaml + end + (?x) + (?= + \s* $ + | \s+ \# + | \s* : (\s|$) + | \s* : [\[\]{},] + | \s* [\[\]{},] + ) + + name + string.unquoted.plain.in.yaml + + + + + include + #flow-node + + + begin + :(?=\s|$|[\[\]{},]) + captures + + 0 + + name + punctuation.separator.key-value.mapping.yaml + + + end + (?=[},\]]) + name + meta.flow-pair.yaml + patterns + + + include + #flow-value + + + + + + flow-scalar + + patterns + + + include + #flow-scalar-double-quoted + + + include + #flow-scalar-single-quoted + + + include + #flow-scalar-plain-in + + + + flow-scalar-double-quoted + + begin + " + beginCaptures + + 0 + + name + punctuation.definition.string.begin.yaml + + + end + " + endCaptures + + 0 + + name + punctuation.definition.string.end.yaml + + + name + string.quoted.double.yaml + patterns + + + match + \\([0abtnvfre "/\\N_Lp]|x\d\d|u\d{4}|U\d{8}) + name + constant.character.escape.yaml + + + match + \\\n + name + constant.character.escape.double-quoted.newline.yaml + + + + flow-scalar-plain-in + + patterns + + + include + #flow-scalar-plain-in-implicit-type + + + begin + (?x) + [^\s[-?:,\[\]{}#&*!|>'"%@`]] + | [?:-] [^\s[\[\]{},]] + + end + (?x) + (?= + \s* $ + | \s+ \# + | \s* : (\s|$) + | \s* : [\[\]{},] + | \s* [\[\]{},] + ) + + name + string.unquoted.plain.in.yaml + + + + flow-scalar-plain-in-implicit-type + + patterns + + + captures + + 1 + + name + constant.language.null.yaml + + 2 + + name + constant.language.boolean.yaml + + 3 + + name + constant.numeric.integer.yaml + + 4 + + name + constant.numeric.float.yaml + + 5 + + name + constant.other.timestamp.yaml + + 6 + + name + constant.language.value.yaml + + 7 + + name + constant.language.merge.yaml + + + match + (?x) + (?x: + (null|Null|NULL|~) + | (y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF) + | ( + (?: + [-+]? 0b [0-1_]+ # (base 2) + | [-+]? 0 [0-7_]+ # (base 8) + | [-+]? (?: 0|[1-9][0-9_]*) # (base 10) + | [-+]? 0x [0-9a-fA-F_]+ # (base 16) + | [-+]? [1-9] [0-9_]* (?: :[0-5]?[0-9])+ # (base 60) + ) + ) + | ( + (?x: + [-+]? (?: [0-9] [0-9_]*)? \. [0-9.]* (?: [eE] [-+] [0-9]+)? # (base 10) + | [-+]? [0-9] [0-9_]* (?: :[0-5]?[0-9])+ \. [0-9_]* # (base 60) + | [-+]? \. (?: inf|Inf|INF) # (infinity) + | \. (?: nan|NaN|NAN) # (not a number) + ) + ) + | ( + (?x: + \d{4} - \d{2} - \d{2} # (y-m-d) + | \d{4} # (year) + - \d{1,2} # (month) + - \d{1,2} # (day) + (?: [Tt] | [ \t]+) \d{1,2} # (hour) + : \d{2} # (minute) + : \d{2} # (second) + (?: \.\d*)? # (fraction) + (?: + (?:[ \t]*) Z + | [-+] \d{1,2} (?: :\d{1,2})? + )? # (time zone) + ) + ) + | (=) + | (<<) + ) + (?: + (?= + \s* $ + | \s+ \# + | \s* : (\s|$) + | \s* : [\[\]{},] + | \s* [\[\]{},] + ) + ) + + + + + flow-scalar-plain-out + + patterns + + + include + #flow-scalar-plain-out-implicit-type + + + begin + (?x) + [^\s[-?:,\[\]{}#&*!|>'"%@`]] + | [?:-] \S + + end + (?x) + (?= + \s* $ + | \s+ \# + | \s* : (\s|$) + ) + + name + string.unquoted.plain.out.yaml + + + + flow-scalar-plain-out-implicit-type + + patterns + + + captures + + 1 + + name + constant.language.null.yaml + + 2 + + name + constant.language.boolean.yaml + + 3 + + name + constant.numeric.integer.yaml + + 4 + + name + constant.numeric.float.yaml + + 5 + + name + constant.other.timestamp.yaml + + 6 + + name + constant.language.value.yaml + + 7 + + name + constant.language.merge.yaml + + + match + (?x) + (?x: + (null|Null|NULL|~) + | (y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF) + | ( + (?: + [-+]? 0b [0-1_]+ # (base 2) + | [-+]? 0 [0-7_]+ # (base 8) + | [-+]? (?: 0|[1-9][0-9_]*) # (base 10) + | [-+]? 0x [0-9a-fA-F_]+ # (base 16) + | [-+]? [1-9] [0-9_]* (?: :[0-5]?[0-9])+ # (base 60) + ) + ) + | ( + (?x: + [-+]? (?: [0-9] [0-9_]*)? \. [0-9.]* (?: [eE] [-+] [0-9]+)? # (base 10) + | [-+]? [0-9] [0-9_]* (?: :[0-5]?[0-9])+ \. [0-9_]* # (base 60) + | [-+]? \. (?: inf|Inf|INF) # (infinity) + | \. (?: nan|NaN|NAN) # (not a number) + ) + ) + | ( + (?x: + \d{4} - \d{2} - \d{2} # (y-m-d) + | \d{4} # (year) + - \d{1,2} # (month) + - \d{1,2} # (day) + (?: [Tt] | [ \t]+) \d{1,2} # (hour) + : \d{2} # (minute) + : \d{2} # (second) + (?: \.\d*)? # (fraction) + (?: + (?:[ \t]*) Z + | [-+] \d{1,2} (?: :\d{1,2})? + )? # (time zone) + ) + ) + | (=) + | (<<) + ) + (?x: + (?= + \s* $ + | \s+ \# + | \s* : (\s|$) + ) + ) + + + + + flow-scalar-single-quoted + + begin + ' + beginCaptures + + 0 + + name + punctuation.definition.string.begin.yaml + + + end + '(?!') + endCaptures + + 0 + + name + punctuation.definition.string.end.yaml + + + name + string.quoted.single.yaml + patterns + + + match + '' + name + constant.character.escape.single-quoted.yaml + + + + flow-sequence + + begin + \[ + beginCaptures + + 0 + + name + punctuation.definition.sequence.begin.yaml + + + end + \] + endCaptures + + 0 + + name + punctuation.definition.sequence.end.yaml + + + name + meta.flow-sequence.yaml + patterns + + + include + #prototype + + + match + , + name + punctuation.separator.sequence.yaml + + + include + #flow-pair + + + include + #flow-node + + + + flow-value + + patterns + + + begin + \G(?![},\]]) + end + (?=[},\]]) + name + meta.flow-pair.value.yaml + patterns + + + include + #flow-node + + + + + + node + + patterns + + + include + #block-node + + + + property + + begin + (?=!|&) + end + (?!\G) + name + meta.property.yaml + patterns + + + captures + + 1 + + name + keyword.control.property.anchor.yaml + + 2 + + name + punctuation.definition.anchor.yaml + + 3 + + name + entity.name.type.anchor.yaml + + 4 + + name + invalid.illegal.character.anchor.yaml + + + match + \G((&))([^\s\[\]/{/},]+)(\S+)? + + + match + (?x) + \G + (?: + ! < (?: %[0-9A-Fa-f]{2} | [0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]] )+ > + | (?:!(?:[0-9A-Za-z\-]*!)?) (?: %[0-9A-Fa-f]{2} | [0-9A-Za-z\-#;/?:@&=+$_.~*'()] )+ + | ! + ) + (?=\ |\t|$) + + name + storage.type.tag-handle.yaml + + + match + \S+ + name + invalid.illegal.tag-handle.yaml + + + + prototype + + patterns + + + include + #comment + + + include + #property + + + + + scopeName + source.yaml + uuid + 686AD6AE-33F3-4493-9512-9E9FC1D5417F + + diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/aspvbnet.plist b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/aspvbnet.plist similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/aspvbnet.plist rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/aspvbnet.plist diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/groovy.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/groovy.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/groovy.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/groovy.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/html.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/html.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/html.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/html.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/html2.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/html2.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/html2.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/html2.json diff --git a/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/infinite-loop.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/infinite-loop.json new file mode 100644 index 000000000..a0b5e6b36 --- /dev/null +++ b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/infinite-loop.json @@ -0,0 +1,79 @@ +{ + "name": "infinite-loop-grammar", + "scopeName": "source.infinite-loop", + "patterns": [ + { + "name": "start", + "begin": "\\A", + "end": "$", + "patterns": [ + { + "name": "negative-look-ahead", + "match": "(?!a)" + } + ] + }, + { + "include": "#test" + }, + { + "include": "#not_a_problem" + } + ], + "repository": { + "test": { + "name": "test", + "begin": "(?=test)", + "end": "$", + "patterns": [ + { + "include": "#test_this" + } + ] + }, + "test_this": { + "name": "test_this", + "begin": "(?=test this)", + "end": "$", + "patterns": [ + { + "include": "#test_this_line" + } + ] + }, + "test_this_line": { + "name": "test_this_line", + "begin": "(?=test this line)", + "end": "$", + "patterns": [ + { + "include": "#test" + } + ] + }, + "spaces": + { + "name": "spaces", + "begin": "^(?=\\s)", + "end": "(?=\\S)" + }, + "not_a_problem": + { + "name": "not_a_problem", + "begin": "(?=not)", + "end": "\\z", + "patterns": [ + { + "name": "not", + "match": "\\Gnot" + }, + { + "include": "#not_a_problem" + }, + { + "include": "#spaces" + } + ] + } + } +} \ No newline at end of file diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/javascript.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/javascript.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/javascript.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/javascript.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/markdown.plist b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/markdown.plist similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/markdown.plist rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/markdown.plist diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/php.plist b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/php.plist similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/php.plist rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/php.plist diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/testlang12.plist b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/testlang12.plist similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/testlang12.plist rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/testlang12.plist diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/whileLang.plist b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/whileLang.plist similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/fixtures/whileLang.plist rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/fixtures/whileLang.plist diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/tests.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/tests.json similarity index 72% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/tests.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/tests.json index 59652aa00..5e80f11b7 100644 --- a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/tests.json +++ b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/tests.json @@ -1253,5 +1253,580 @@ ] } ] + }, + { + "grammars": [ + "fixtures/Jade22.json" + ], + "grammarPath": "fixtures/Jade22.json", + "desc": "Issue #22", + "lines": [ + { + "line": ".class One #[span text.] Two text.", + "tokens": [ + { + "scopes": [ + "text.jade", + "constant.language.js" + ], + "value": ".class" + }, + { + "scopes": [ + "text.jade" + ], + "value": " One " + }, + { + "scopes": [ + "text.jade", + "inline.jade", + "entity.name.function.jade" + ], + "value": "#[" + }, + { + "scopes": [ + "text.jade", + "inline.jade", + "tag.inline.jade", + "meta.tag.other", + "entity.name.tag.jade" + ], + "value": "span" + }, + { + "scopes": [ + "text.jade", + "inline.jade" + ], + "value": " text." + }, + { + "scopes": [ + "text.jade", + "inline.jade", + "entity.name.function.jade" + ], + "value": "]" + }, + { + "scopes": [ + "text.jade" + ], + "value": " Two text." + } + ] + } + ] + }, + { + "grammars": [ + "fixtures/Pug.tmLanguage" + ], + "grammarPath": "fixtures/Pug.tmLanguage", + "desc": "Issue #82", + "lines": [ + { + "line": "li: custom-link.has-text-primary(to=\"/\")", + "tokens": [ + { + "scopes": [ + "text.pug", + "meta.tag.other", + "entity.name.tag.pug" + ], + "value": "li" + }, + { + "scopes": [ + "text.pug" + ], + "value": ": " + }, + { + "scopes": [ + "text.pug", + "meta.tag.other", + "entity.name.tag.pug" + ], + "value": "custom-link" + }, + { + "scopes": [ + "text.pug", + "entity.other.attribute-name.class.pug" + ], + "value": ".has-text-primary" + }, + { + "scopes": [ + "text.pug", + "meta.tag.other", + "constant.name.attribute.tag.pug" + ], + "value": "(" + }, + { + "scopes": [ + "text.pug", + "meta.tag.other", + "entity.other.attribute-name.tag.pug" + ], + "value": "to" + }, + { + "scopes": [ + "text.pug", + "meta.tag.other", + "attribute_value" + ], + "value": "=" + }, + { + "scopes": [ + "text.pug", + "meta.tag.other", + "attribute_value", + "string.quoted.pug" + ], + "value": "\"" + }, + { + "scopes": [ + "text.pug", + "meta.tag.other", + "attribute_value", + "string.quoted.pug" + ], + "value": "/" + }, + { + "scopes": [ + "text.pug", + "meta.tag.other", + "attribute_value", + "string.quoted.pug" + ], + "value": "\"" + }, + { + "scopes": [ + "text.pug", + "meta.tag.other", + "constant.name.attribute.tag.pug" + ], + "value": ")" + } + ] + } + ] + }, + { + "grammars": [ + "fixtures/66.plist" + ], + "grammarPath": "fixtures/66.plist", + "desc": "Issue #66", + "lines": [ + { + "line": "Just some text", + "tokens": [ + { + "value": "J", + "scopes": [ + "text.test", + "comment" + ] + }, + { + "value": "ust some text", + "scopes": [ + "text.test", + "comment" + ] + } + ] + }, + { + "line": "which contains undefined and then", + "tokens": [ + { + "value": "which contains undefined and then", + "scopes": [ + "text.test", + "comment" + ] + } + ] + }, + { + "line": "more text", + "tokens": [ + { + "value": "more text", + "scopes": [ + "text.test", + "comment" + ] + } + ] + } + ] + }, + { + "grammars": [ + "fixtures/105.grammarA.json", + "fixtures/105.grammarB.json" + ], + "grammarPath": "fixtures/105.grammarA.json", + "desc": "Issue #105", + "lines": [ + { + "line": "embedStart", + "tokens": [ + { + "value": "embedStart", + "scopes": [ + "source.test" + ] + } + ] + }, + { + "line": "testStart", + "tokens": [ + { + "value": "testStart", + "scopes": [ + "source.test" + ] + } + ] + }, + { + "line": "some test pattern", + "tokens": [ + { + "value": "some test pattern", + "scopes": [ + "source.test", + "test.name" + ] + } + ] + } + ] + }, + { + "grammars": [ + "fixtures/YAML.tmLanguage" + ], + "grammarPath": "fixtures/YAML.tmLanguage", + "desc": "Issue #119", + "lines": [ + { + "line": "- run:", + "tokens": [ + { + "scopes": [ + "source.yaml", + "punctuation.definition.block.sequence.item.yaml" + ], + "value": "-" + }, + { + "scopes": [ + "source.yaml" + ], + "value": " " + }, + { + "scopes": [ + "source.yaml", + "string.unquoted.plain.out.yaml", + "entity.name.tag.yaml" + ], + "value": "r" + }, + { + "scopes": [ + "source.yaml", + "string.unquoted.plain.out.yaml", + "entity.name.tag.yaml" + ], + "value": "un" + }, + { + "scopes": [ + "source.yaml", + "punctuation.separator.key-value.mapping.yaml" + ], + "value": ":" + } + ] + }, + { + "line": " command: |", + "tokens": [ + { + "scopes": [ + "source.yaml" + ], + "value": " " + }, + { + "scopes": [ + "source.yaml", + "string.unquoted.plain.out.yaml", + "entity.name.tag.yaml" + ], + "value": "c" + }, + { + "scopes": [ + "source.yaml", + "string.unquoted.plain.out.yaml", + "entity.name.tag.yaml" + ], + "value": "ommand" + }, + { + "scopes": [ + "source.yaml", + "punctuation.separator.key-value.mapping.yaml" + ], + "value": ":" + }, + { + "scopes": [ + "source.yaml" + ], + "value": " " + }, + { + "scopes": [ + "source.yaml", + "keyword.control.flow.block-scalar.literal.yaml" + ], + "value": "|" + } + ] + }, + { + "line": " docker run \\", + "tokens": [ + { + "scopes": [ + "source.yaml", + "string.unquoted.block.yaml" + ], + "value": " " + }, + { + "scopes": [ + "source.yaml", + "string.unquoted.block.yaml" + ], + "value": "docker run \\" + } + ] + }, + { + "line": " sh -c \"\\", + "tokens": [ + { + "scopes": [ + "source.yaml", + "string.unquoted.block.yaml" + ], + "value": " sh -c \"\\" + } + ] + }, + { + "line": " command3", + "tokens": [ + { + "scopes": [ + "source.yaml", + "string.unquoted.block.yaml" + ], + "value": " command3" + } + ] + }, + { + "line": " \"", + "tokens": [ + { + "scopes": [ + "source.yaml", + "string.unquoted.block.yaml" + ], + "value": " \"" + } + ] + }, + { + "line": "- run:", + "tokens": [ + { + "scopes": [ + "source.yaml", + "punctuation.definition.block.sequence.item.yaml" + ], + "value": "-" + }, + { + "scopes": [ + "source.yaml" + ], + "value": " " + }, + { + "scopes": [ + "source.yaml", + "string.unquoted.plain.out.yaml", + "entity.name.tag.yaml" + ], + "value": "r" + }, + { + "scopes": [ + "source.yaml", + "string.unquoted.plain.out.yaml", + "entity.name.tag.yaml" + ], + "value": "un" + }, + { + "scopes": [ + "source.yaml", + "punctuation.separator.key-value.mapping.yaml" + ], + "value": ":" + } + ] + } + ] + }, + { + "grammars": [ + "fixtures/infinite-loop.json" + ], + "grammarPath": "fixtures/infinite-loop.json", + "desc": "Issue #145", + "lines": [ + { + "line": "abc", + "tokens": [ + { + "value": "a", + "scopes": [ + "source.infinite-loop", + "start" + ] + }, + { + "value": "bc", + "scopes": [ + "source.infinite-loop" + ] + } + ] + }, + { + "line": "test this line", + "tokens": [ + { + "value": "test this line", + "scopes": [ + "source.infinite-loop", + "test", + "test_this", + "test_this_line" + ] + } + ] + }, + { + "line": "not", + "tokens": [ + { + "value": "not", + "scopes": [ + "source.infinite-loop", + "test", + "test_this", + "test_this_line" + ] + } + ] + }, + { + "line": " not", + "tokens": [ + { + "value": " ", + "scopes": [ + "source.infinite-loop" + ] + }, + { + "value": "not", + "scopes": [ + "source.infinite-loop", + "not_a_problem", + "not" + ] + } + ] + }, + { + "line": " not", + "tokens": [ + { + "value": " ", + "scopes": [ + "source.infinite-loop", + "not_a_problem", + "spaces" + ] + }, + { + "value": "not", + "scopes": [ + "source.infinite-loop", + "not_a_problem", + "not_a_problem", + "not" + ] + } + ] + } + ] + }, + { + "grammars": [ + "fixtures/147.grammar.json" + ], + "grammarPath": "fixtures/147.grammar.json", + "desc": "Issue #147", + "lines": [ + { + "line": "Function", + "tokens": [ + { + "value": "Function", + "scopes": [ + "source.test", + "storage.type.Function", + "keyword.declaration.Function" + ] + } + ] + } + ] } -] \ No newline at end of file +] diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/whileTests.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/whileTests.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/suite1/whileTests.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/suite1/whileTests.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/.gitignore b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/.gitignore similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/.gitignore rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/.gitignore diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/Abyss.tmTheme b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/Abyss.tmTheme similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/Abyss.tmTheme rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/Abyss.tmTheme diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/Kimbie_dark.tmTheme b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/Kimbie_dark.tmTheme similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/Kimbie_dark.tmTheme rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/Kimbie_dark.tmTheme diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/Monokai.tmTheme b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/Monokai.tmTheme similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/Monokai.tmTheme rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/Monokai.tmTheme diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/QuietLight.tmTheme b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/QuietLight.tmTheme similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/QuietLight.tmTheme rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/QuietLight.tmTheme diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/Solarized-dark.tmTheme b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/Solarized-dark.tmTheme similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/Solarized-dark.tmTheme rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/Solarized-dark.tmTheme diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/Solarized-light.tmTheme b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/Solarized-light.tmTheme similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/Solarized-light.tmTheme rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/Solarized-light.tmTheme diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/Tomorrow-Night-Blue.tmTheme b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/Tomorrow-Night-Blue.tmTheme similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/Tomorrow-Night-Blue.tmTheme rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/Tomorrow-Night-Blue.tmTheme diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/dark_plus.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/dark_plus.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/dark_plus.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/dark_plus.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/dark_vs.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/dark_vs.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/dark_vs.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/dark_vs.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/diff.css b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/diff.css similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/diff.css rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/diff.css diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/diff.js b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/diff.js similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/diff.js rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/diff.js diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/diff.ts b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/diff.ts similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/diff.ts rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/diff.ts diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/dimmed-monokai.tmTheme b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/dimmed-monokai.tmTheme similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/dimmed-monokai.tmTheme rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/dimmed-monokai.tmTheme diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/go/colorize-fixtures/test-13777.go b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/go/colorize-fixtures/test-13777.go similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/go/colorize-fixtures/test-13777.go rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/go/colorize-fixtures/test-13777.go diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/go/colorize-fixtures/test.go b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/go/colorize-fixtures/test.go similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/go/colorize-fixtures/test.go rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/go/colorize-fixtures/test.go diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/go/colorize-results/test-13777_go.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/go/colorize-results/test-13777_go.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/go/colorize-results/test-13777_go.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/go/colorize-results/test-13777_go.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/go/colorize-results/test_go.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/go/colorize-results/test_go.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/go/colorize-results/test_go.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/go/colorize-results/test_go.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/go/go.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/go/go.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/go/go.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/go/go.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/grammars.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/grammars.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/grammars.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/grammars.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/hc_black.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/hc_black.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/hc_black.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/hc_black.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/languages.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/languages.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/languages.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/languages.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/light_plus.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/light_plus.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/light_plus.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/light_plus.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/light_vs.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/light_vs.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/light_vs.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/light_vs.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/red.tmTheme b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/red.tmTheme similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/red.tmTheme rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/red.tmTheme diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/ASPVBnet.plist b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/ASPVBnet.plist similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/ASPVBnet.plist rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/ASPVBnet.plist diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Batch File.tmLanguage b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Batch File.tmLanguage similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Batch File.tmLanguage rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Batch File.tmLanguage diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Clojure.tmLanguage b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Clojure.tmLanguage similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Clojure.tmLanguage rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Clojure.tmLanguage diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Dockerfile.tmLanguage b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Dockerfile.tmLanguage similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Dockerfile.tmLanguage rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Dockerfile.tmLanguage diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Groovy.tmLanguage b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Groovy.tmLanguage similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Groovy.tmLanguage rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Groovy.tmLanguage diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Handlebars.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Handlebars.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Handlebars.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Handlebars.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/JSON.tmLanguage b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/JSON.tmLanguage similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/JSON.tmLanguage rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/JSON.tmLanguage diff --git a/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Jade.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Jade.json new file mode 100644 index 000000000..0bb3f8882 --- /dev/null +++ b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Jade.json @@ -0,0 +1,964 @@ +{ + "fileTypes": [ + "jade" + ], + "name": "Jade", + "patterns": [ + { + "comment": "Doctype declaration.", + "match": "^(!!!|doctype)(\\s*[a-zA-Z0-9-_]+)?", + "name": "meta.tag.sgml.doctype.html" + }, + { + "begin": "^(\\s*)//-", + "comment": "Unbuffered (jade-only) comments.", + "end": "^(?!(\\1\\s)|\\s*$)", + "name": "comment.unbuffered.block.jade" + }, + { + "begin": "^(\\s*)//", + "comment": "Buffered (html) comments.", + "end": "^(?!(\\1\\s)|\\s*$)", + "name": "string.comment.buffered.block.jade", + "patterns": [ + { + "captures": { + "1": { + "name": "invalid.illegal.comment.comment.block.jade" + } + }, + "comment": "Buffered comments inside buffered comments will generate invalid html.", + "match": "^\\s*(//)(?!-)", + "name": "string.comment.buffered.block.jade" + } + ] + }, + { + "begin": "^(\\s*)-$", + "comment": "Unbuffered code block.", + "end": "^(?!(\\1\\s)|\\s*$)", + "name": "source.js", + "patterns": [ + { + "include": "source.js" + } + ] + }, + { + "begin": "^(\\s*)(script)(?=[.#(\\s])((?![^\\n]*type=)|(?=[^\\n]*(text|application)/javascript))", + "beginCaptures": { + "2": { + "name": "entity.name.tag.script.jade" + } + }, + "comment": "Script tag with JavaScript code.", + "end": "^(?!(\\1\\s)|\\s*$)", + "name": "meta.tag.other", + "patterns": [ + { + "begin": "\\G(?=\\()", + "end": "$", + "name": "stuff.tag.script.jade", + "patterns": [ + { + "include": "#tag_attributes" + } + ] + }, + { + "begin": "\\G(?=[.#])", + "end": "$", + "name": "stuff.tag.script.jade", + "patterns": [ + { + "include": "#complete_tag" + } + ] + }, + { + "include": "source.js" + } + ] + }, + { + "begin": "^(\\s*)(style)((\\.$)|(?=[.#(].*\\.$))", + "beginCaptures": { + "2": { + "name": "entity.name.tag.script.jade" + } + }, + "comment": "Style tag with CSS code.", + "end": "^(?!(\\1\\s)|\\s*$)", + "name": "meta.tag.other", + "patterns": [ + { + "begin": "\\G(?=\\()", + "end": "$", + "name": "stuff.tag.style.jade", + "patterns": [ + { + "include": "#tag_attributes" + } + ] + }, + { + "begin": "\\G(?=[.#])", + "end": "$", + "name": "stuff.tag.style.jade", + "patterns": [ + { + "include": "#complete_tag" + } + ] + }, + { + "include": "source.css" + } + ] + }, + { + "begin": "^(\\s*):(sass)(?=\\(|$)", + "beginCaptures": { + "2": { + "name": "constant.language.name.sass.filter.jade" + } + }, + "end": "^(?!(\\1\\s)|\\s*$)", + "name": "source.sass.filter.jade", + "patterns": [ + { + "include": "#tag_attributes" + }, + { + "include": "source.sass" + } + ] + }, + { + "begin": "^(\\s*):(less)(?=\\(|$)", + "beginCaptures": { + "2": { + "name": "constant.language.name.less.filter.jade" + } + }, + "end": "^(?!(\\1\\s)|\\s*$)", + "name": "source.less.filter.jade", + "patterns": [ + { + "include": "#tag_attributes" + }, + { + "include": "source.less" + } + ] + }, + { + "begin": "^(\\s*):(stylus)(?=\\(|$)", + "beginCaptures": { + "2": { + "name": "constant.language.name.stylus.filter.jade" + } + }, + "end": "^(?!(\\1\\s)|\\s*$)", + "patterns": [ + { + "include": "#tag_attributes" + }, + { + "include": "source.stylus" + } + ] + }, + { + "begin": "^(\\s*):(coffee(-?script)?)(?=\\(|$)", + "beginCaptures": { + "2": { + "name": "constant.language.name.coffeescript.filter.jade" + } + }, + "end": "^(?!(\\1\\s)|\\s*$)", + "name": "source.coffeescript.filter.jade", + "patterns": [ + { + "include": "#tag_attributes" + }, + { + "include": "source.coffee" + } + ] + }, + { + "begin": "^(\\s*)((:(?=.))|(:$))", + "beginCaptures": { + "4": { + "name": "invalid.illegal.empty.generic.filter.jade" + } + }, + "comment": "Generic Jade filter.", + "end": "^(?!(\\1\\s)|\\s*$)", + "patterns": [ + { + "begin": "\\G(?<=:)(?=.)", + "end": "$", + "name": "name.generic.filter.jade", + "patterns": [ + { + "match": "\\G\\(", + "name": "invalid.illegal.name.generic.filter.jade" + }, + { + "match": "[\\w-]", + "name": "constant.language.name.generic.filter.jade" + }, + { + "include": "#tag_attributes" + }, + { + "match": "\\W", + "name": "invalid.illegal.name.generic.filter.jade" + } + ] + } + ] + }, + { + "begin": "^(\\s*)(?=[\\w.#].*?\\.$)(?=(?:(?:(?:(?:(?:#[\\w-]+)|(?:\\.[\\w-]+))|(?:(?:[#!]\\{[^}]*\\})|(?:\\w(?:(?:[\\w:-]+[\\w-])|(?:[\\w-]*)))))(?:(?:#[\\w-]+)|(?:\\.[\\w-]+)|(?:\\((?:[^()\\'\\\"]*(?:(?:\\'(?:[^\\']|(?:(?|$", + "patterns": [ + { + "include": "#inline_jade" + }, + { + "include": "#interpolated_value" + }, + { + "include": "#interpolated_error" + } + ] + }, + { + "include": "#inline_jade" + }, + { + "include": "#embedded_html" + }, + { + "include": "#html_entity" + }, + { + "include": "#interpolated_value" + }, + { + "include": "#interpolated_error" + } + ] + }, + { + "include": "#complete_tag" + } + ] + } + ], + "repository": { + "blocks_and_includes": { + "captures": { + "1": { + "name": "storage.type.import.include.jade" + }, + "4": { + "name": "variable.control.import.include.jade" + } + }, + "comment": "Template blocks and includes.", + "match": "(extends|include|yield|append|prepend|block( (append|prepend))?)\\s+(.*)$", + "name": "meta.first-class.jade" + }, + "case_conds": { + "begin": "(default|when)((\\s+|(?=:))|$)", + "captures": { + "1": { + "name": "storage.type.function.jade" + } + }, + "comment": "Jade case conditionals.", + "end": "$", + "name": "meta.control.flow.jade", + "patterns": [ + { + "begin": "\\G(?!:)", + "end": "(?=:\\s+)|$", + "name": "js.embedded.control.flow.jade", + "patterns": [ + { + "include": "#case_when_paren" + }, + { + "include": "source.js" + } + ] + }, + { + "begin": ":\\s+", + "end": "$", + "name": "tag.case.control.flow.jade", + "patterns": [ + { + "include": "#complete_tag" + } + ] + } + ] + }, + "case_when_paren": { + "begin": "\\(", + "end": "\\)", + "name": "js.when.control.flow.jade", + "patterns": [ + { + "include": "#case_when_paren" + }, + { + "match": ":", + "name": "invalid.illegal.name.tag.jade" + }, + { + "include": "source.js" + } + ] + }, + "complete_tag": { + "begin": "(?=[\\w.#])|(:\\s*)", + "end": "(\\.?$)|(?=:.)", + "patterns": [ + { + "include": "#blocks_and_includes" + }, + { + "include": "#unbuffered_code" + }, + { + "include": "#mixin_call" + }, + { + "include": "#flow_control" + }, + { + "match": "(?<=:)\\w.*$", + "name": "invalid.illegal.name.tag.jade" + }, + { + "include": "#tag_name" + }, + { + "include": "#tag_id" + }, + { + "include": "#tag_classes" + }, + { + "include": "#tag_attributes" + }, + { + "include": "#tag_mixin_attributes" + }, + { + "captures": { + "2": { + "name": "invalid.illegal.end.tag.jade" + }, + "4": { + "name": "invalid.illegal.end.tag.jade" + } + }, + "match": "((\\.)\\s+$)|((:)\\s*$)" + }, + { + "include": "#printed_expression" + }, + { + "include": "#tag_text" + } + ] + }, + "embedded_html": { + "begin": "(?=<[^>]*>)", + "end": "$|(?=>)", + "name": "html", + "patterns": [ + { + "include": "text.html.basic" + }, + { + "include": "#interpolated_value" + }, + { + "include": "#interpolated_error" + } + ] + }, + "flow_control": { + "begin": "(for|if|else if|else|each|until|while|unless|case)(\\s+|$)", + "captures": { + "1": { + "name": "storage.type.function.jade" + } + }, + "comment": "Jade control flow.", + "end": "$", + "name": "meta.control.flow.jade", + "patterns": [ + { + "begin": "", + "end": "$", + "name": "js.embedded.control.flow.jade", + "patterns": [ + { + "include": "source.js" + } + ] + } + ] + }, + "html_entity": { + "patterns": [ + { + "match": "(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)", + "name": "constant.character.entity.html.text.jade" + }, + { + "match": "[<>&]", + "name": "invalid.illegal.html_entity.text.jade" + } + ] + }, + "inline_jade": { + "begin": "(?:?/])|\\))", + "name": "attribute_value", + "patterns": [ + { + "include": "#string" + }, + { + "include": "#js_parens" + }, + { + "include": "#js_brackets" + }, + { + "include": "#js_braces" + }, + { + "include": "source.js" + } + ] + }, + { + "begin": "(?<=[%&*-+~|<>:?/])\\s+", + "end": "$|(?=,|(?:\\s+[^!%&*-+~|<>:?/])|\\))", + "name": "attribute_value2", + "patterns": [ + { + "include": "#string" + }, + { + "include": "#js_parens" + }, + { + "include": "#js_brackets" + }, + { + "include": "#js_braces" + }, + { + "include": "source.js" + } + ] + } + ] + }, + "tag_classes": { + "captures": { + "1": { + "name": "invalid.illegal.tag.jade" + } + }, + "match": "\\.([^\\w-])?[\\w-]*", + "name": "constant.language.js" + }, + "tag_id": { + "match": "#[\\w-]+", + "name": "constant.id.tag.jade" + }, + "tag_mixin_attributes": { + "begin": "(&attributes\\()", + "captures": { + "1": { + "name": "entity.name.function.jade" + } + }, + "end": "(\\))", + "name": "meta.tag.other", + "patterns": [ + { + "match": "attributes(?=\\))", + "name": "storage.type.keyword.jade" + }, + { + "include": "source.js" + } + ] + }, + "tag_name": { + "begin": "([#!]\\{(?=.*?\\}))|(\\w(([\\w:-]+[\\w-])|([\\w-]*)))", + "end": "(\\G(? + diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/PowershellSyntax.tmLanguage b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/PowershellSyntax.tmLanguage similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/PowershellSyntax.tmLanguage rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/PowershellSyntax.tmLanguage diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/R.plist b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/R.plist similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/R.plist rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/R.plist diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Regular Expressions (JavaScript).tmLanguage b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Regular Expressions (JavaScript).tmLanguage similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Regular Expressions (JavaScript).tmLanguage rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Regular Expressions (JavaScript).tmLanguage diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Ruby.plist b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Ruby.plist similarity index 99% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Ruby.plist rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Ruby.plist index 04e41fabb..909581a5f 100644 --- a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Ruby.plist +++ b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Ruby.plist @@ -381,7 +381,7 @@ ( (?>[a-zA-Z_]\w*(?>\.|::))? # a method name prefix (?>[a-zA-Z_]\w*(?>[?!]|=(?!>))? # the method name |===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\]=?) ) # …or an operator method - \s*(\() # the openning parenthesis for arguments + \s*(\() # the opening parenthesis for arguments beginCaptures diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/SQL.plist b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/SQL.plist similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/SQL.plist rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/SQL.plist diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Shell-Unix-Bash.tmLanguage.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Shell-Unix-Bash.tmLanguage.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/Shell-Unix-Bash.tmLanguage.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/Shell-Unix-Bash.tmLanguage.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/TypeScript.tmLanguage.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/TypeScript.tmLanguage.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/TypeScript.tmLanguage.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/TypeScript.tmLanguage.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/TypeScriptReact.tmLanguage.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/TypeScriptReact.tmLanguage.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/TypeScriptReact.tmLanguage.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/TypeScriptReact.tmLanguage.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/c++.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/c++.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/c++.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/c++.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/c.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/c.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/c.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/c.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/coffeescript.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/coffeescript.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/coffeescript.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/coffeescript.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/cshtml.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/cshtml.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/cshtml.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/cshtml.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/css.plist b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/css.plist similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/css.plist rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/css.plist diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/diff.tmLanguage b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/diff.tmLanguage similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/diff.tmLanguage rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/diff.tmLanguage diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/fsharp.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/fsharp.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/fsharp.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/fsharp.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/git-commit.tmLanguage b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/git-commit.tmLanguage similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/git-commit.tmLanguage rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/git-commit.tmLanguage diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/git-rebase.tmLanguage b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/git-rebase.tmLanguage similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/git-rebase.tmLanguage rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/git-rebase.tmLanguage diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/go.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/go.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/go.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/go.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/html.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/html.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/html.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/html.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/java.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/java.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/java.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/java.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/less.tmLanguage.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/less.tmLanguage.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/less.tmLanguage.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/less.tmLanguage.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/lua.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/lua.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/lua.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/lua.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/markdown.tmLanguage b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/markdown.tmLanguage similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/markdown.tmLanguage rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/markdown.tmLanguage diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/php.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/php.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/php.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/php.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/properties.plist b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/properties.plist similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/properties.plist rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/properties.plist diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/rust.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/rust.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/rust.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/rust.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/scss.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/scss.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/scss.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/scss.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/shaderlab.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/shaderlab.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/shaderlab.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/shaderlab.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/swift.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/swift.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/swift.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/swift.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/xml.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/xml.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/xml.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/xml.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/xsl.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/xsl.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/xsl.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/xsl.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/yaml.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/yaml.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/syntaxes/yaml.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/syntaxes/yaml.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/12750.html b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/12750.html similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/12750.html rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/12750.html diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/12750.html.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/12750.html.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/12750.html.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/12750.html.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/12750.html.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/12750.html.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/12750.html.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/12750.html.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/13448.html b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/13448.html similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/13448.html rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/13448.html diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/13448.html.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/13448.html.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/13448.html.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/13448.html.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/13448.html.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/13448.html.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/13448.html.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/13448.html.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/14119.less b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/14119.less similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/14119.less rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/14119.less diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/14119.less.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/14119.less.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/14119.less.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/14119.less.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/14119.less.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/14119.less.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/14119.less.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/14119.less.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/COMMIT_EDITMSG b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/COMMIT_EDITMSG similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/COMMIT_EDITMSG rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/COMMIT_EDITMSG diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/COMMIT_EDITMSG.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/COMMIT_EDITMSG.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/COMMIT_EDITMSG.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/COMMIT_EDITMSG.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/Dockerfile b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/Dockerfile similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/Dockerfile rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/Dockerfile diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/Dockerfile.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/Dockerfile.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/Dockerfile.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/Dockerfile.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/basic.java b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/basic.java similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/basic.java rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/basic.java diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/basic.java.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/basic.java.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/basic.java.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/basic.java.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/basic.java.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/basic.java.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/basic.java.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/basic.java.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/git-rebase-todo b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/git-rebase-todo similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/git-rebase-todo rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/git-rebase-todo diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/git-rebase-todo.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/git-rebase-todo.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/git-rebase-todo.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/git-rebase-todo.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-1550.yaml b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-1550.yaml similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-1550.yaml rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-1550.yaml diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-1550.yaml.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-1550.yaml.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-1550.yaml.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-1550.yaml.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-1550.yaml.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-1550.yaml.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-1550.yaml.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-1550.yaml.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-4008.yaml b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-4008.yaml similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-4008.yaml rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-4008.yaml diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-4008.yaml.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-4008.yaml.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-4008.yaml.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-4008.yaml.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-4008.yaml.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-4008.yaml.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-4008.yaml.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-4008.yaml.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-6303.yaml b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-6303.yaml similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-6303.yaml rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-6303.yaml diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-6303.yaml.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-6303.yaml.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-6303.yaml.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-6303.yaml.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-6303.yaml.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-6303.yaml.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/issue-6303.yaml.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/issue-6303.yaml.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/makefile b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/makefile similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/makefile rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/makefile diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/makefile.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/makefile.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/makefile.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/makefile.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/makefile.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/makefile.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/makefile.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/makefile.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-13777.go b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-13777.go similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-13777.go rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-13777.go diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-13777.go.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-13777.go.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-13777.go.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-13777.go.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-4287.jade b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-4287.jade similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-4287.jade rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-4287.jade diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-4287.jade.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-4287.jade.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-4287.jade.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-4287.jade.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-6611.rs b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-6611.rs similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-6611.rs rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-6611.rs diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-6611.rs.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-6611.rs.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-6611.rs.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-6611.rs.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-6611.rs.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-6611.rs.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-6611.rs.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-6611.rs.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-7115.xml b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-7115.xml similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-7115.xml rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-7115.xml diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-7115.xml.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-7115.xml.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-7115.xml.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-7115.xml.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-7115.xml.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-7115.xml.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-7115.xml.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-7115.xml.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-brackets.tsx b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-brackets.tsx similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-brackets.tsx rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-brackets.tsx diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-brackets.tsx.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-brackets.tsx.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-brackets.tsx.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-brackets.tsx.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-brackets.tsx.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-brackets.tsx.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-brackets.tsx.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-brackets.tsx.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-cssvariables.less b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-cssvariables.less similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-cssvariables.less rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-cssvariables.less diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-cssvariables.less.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-cssvariables.less.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-cssvariables.less.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-cssvariables.less.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-cssvariables.less.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-cssvariables.less.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-cssvariables.less.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-cssvariables.less.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-cssvariables.scss b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-cssvariables.scss similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-cssvariables.scss rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-cssvariables.scss diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-cssvariables.scss.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-cssvariables.scss.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-cssvariables.scss.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-cssvariables.scss.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-cssvariables.scss.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-cssvariables.scss.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-cssvariables.scss.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-cssvariables.scss.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-function-inv.ts b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-function-inv.ts similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-function-inv.ts rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-function-inv.ts diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-function-inv.ts.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-function-inv.ts.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-function-inv.ts.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-function-inv.ts.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-function-inv.ts.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-function-inv.ts.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-function-inv.ts.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-function-inv.ts.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue11.ts b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue11.ts similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue11.ts rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue11.ts diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue11.ts.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue11.ts.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue11.ts.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue11.ts.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue11.ts.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue11.ts.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue11.ts.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue11.ts.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue5431.ts b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue5431.ts similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue5431.ts rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue5431.ts diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue5431.ts.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue5431.ts.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue5431.ts.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue5431.ts.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue5431.ts.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue5431.ts.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue5431.ts.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue5431.ts.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue5465.ts b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue5465.ts similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue5465.ts rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue5465.ts diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue5465.ts.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue5465.ts.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue5465.ts.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue5465.ts.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue5566.ts b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue5566.ts similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue5566.ts rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue5566.ts diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue5566.ts.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue5566.ts.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue5566.ts.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue5566.ts.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue5566.ts.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue5566.ts.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-issue5566.ts.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-issue5566.ts.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-keywords.ts b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-keywords.ts similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-keywords.ts rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-keywords.ts diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-keywords.ts.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-keywords.ts.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-keywords.ts.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-keywords.ts.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-keywords.ts.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-keywords.ts.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-keywords.ts.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-keywords.ts.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-members.ts b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-members.ts similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-members.ts rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-members.ts diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-members.ts.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-members.ts.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-members.ts.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-members.ts.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-members.ts.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-members.ts.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-members.ts.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-members.ts.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-object-literals.ts b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-object-literals.ts similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-object-literals.ts rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-object-literals.ts diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-object-literals.ts.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-object-literals.ts.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-object-literals.ts.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-object-literals.ts.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-object-literals.ts.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-object-literals.ts.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-object-literals.ts.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-object-literals.ts.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-regex.coffee b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-regex.coffee similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-regex.coffee rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-regex.coffee diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-regex.coffee.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-regex.coffee.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-regex.coffee.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-regex.coffee.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-regex.coffee.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-regex.coffee.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-regex.coffee.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-regex.coffee.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-strings.ts b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-strings.ts similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-strings.ts rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-strings.ts diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-strings.ts.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-strings.ts.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-strings.ts.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-strings.ts.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-strings.ts.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-strings.ts.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-strings.ts.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-strings.ts.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-this.ts b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-this.ts similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-this.ts rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-this.ts diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-this.ts.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-this.ts.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-this.ts.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-this.ts.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-variables.css b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-variables.css similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-variables.css rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-variables.css diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-variables.css.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-variables.css.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-variables.css.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-variables.css.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-variables.css.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-variables.css.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test-variables.css.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test-variables.css.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.bat b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.bat similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.bat rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.bat diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.bat.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.bat.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.bat.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.bat.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.c b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.c similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.c rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.c diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.c.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.c.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.c.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.c.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.c.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.c.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.c.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.c.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cc b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cc similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cc rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cc diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cc.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cc.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cc.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cc.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cc.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cc.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cc.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cc.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.clj b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.clj similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.clj rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.clj diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.clj.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.clj.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.clj.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.clj.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.clj.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.clj.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.clj.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.clj.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.coffee b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.coffee similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.coffee rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.coffee diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.coffee.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.coffee.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.coffee.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.coffee.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.coffee.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.coffee.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.coffee.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.coffee.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cpp b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cpp similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cpp rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cpp diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cpp.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cpp.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cpp.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cpp.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cpp.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cpp.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cpp.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cpp.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cshtml b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cshtml similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cshtml rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cshtml diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cshtml.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cshtml.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cshtml.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cshtml.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cshtml.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cshtml.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.cshtml.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.cshtml.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.css b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.css similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.css rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.css diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.css.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.css.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.css.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.css.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.css.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.css.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.css.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.css.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.diff b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.diff similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.diff rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.diff diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.diff.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.diff.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.diff.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.diff.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.diff.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.diff.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.diff.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.diff.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.fs b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.fs similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.fs rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.fs diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.fs.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.fs.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.fs.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.fs.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.fs.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.fs.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.fs.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.fs.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.go b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.go similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.go rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.go diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.go.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.go.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.go.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.go.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.go.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.go.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.go.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.go.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.groovy b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.groovy similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.groovy rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.groovy diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.groovy.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.groovy.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.groovy.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.groovy.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.groovy.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.groovy.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.groovy.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.groovy.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.handlebars b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.handlebars similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.handlebars rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.handlebars diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.handlebars.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.handlebars.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.handlebars.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.handlebars.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.handlebars.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.handlebars.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.handlebars.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.handlebars.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.hbs b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.hbs similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.hbs rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.hbs diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.hbs.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.hbs.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.hbs.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.hbs.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.hbs.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.hbs.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.hbs.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.hbs.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.html b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.html similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.html rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.html diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.html.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.html.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.html.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.html.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.html.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.html.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.html.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.html.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.ini b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.ini similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.ini rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.ini diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.ini.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.ini.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.ini.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.ini.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.jade b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.jade similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.jade rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.jade diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.jade.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.jade.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.jade.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.jade.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.jade.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.jade.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.jade.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.jade.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.js b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.js similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.js rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.js diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.js.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.js.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.js.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.js.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.js.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.js.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.js.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.js.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.json.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.json.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.json.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.json.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.json.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.json.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.json.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.json.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.jsx b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.jsx similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.jsx rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.jsx diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.jsx.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.jsx.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.jsx.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.jsx.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.jsx.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.jsx.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.jsx.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.jsx.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.less b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.less similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.less rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.less diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.less.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.less.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.less.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.less.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.less.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.less.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.less.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.less.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.lua b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.lua similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.lua rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.lua diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.lua.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.lua.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.lua.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.lua.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.m b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.m similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.m rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.m diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.m.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.m.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.m.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.m.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.m.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.m.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.m.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.m.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.md b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.md similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.md rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.md diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.md.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.md.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.md.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.md.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.md.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.md.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.md.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.md.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.php b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.php similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.php rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.php diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.php.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.php.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.php.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.php.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.php.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.php.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.php.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.php.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.pl b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.pl similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.pl rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.pl diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.pl.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.pl.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.pl.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.pl.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.pl.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.pl.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.pl.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.pl.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.ps1 b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.ps1 similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.ps1 rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.ps1 diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.ps1.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.ps1.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.ps1.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.ps1.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.ps1.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.ps1.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.ps1.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.ps1.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.py b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.py similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.py rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.py diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.py.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.py.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.py.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.py.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.py.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.py.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.py.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.py.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.r b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.r similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.r rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.r diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.r.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.r.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.r.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.r.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.rb b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.rb similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.rb rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.rb diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.rb.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.rb.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.rb.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.rb.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.rb.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.rb.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.rb.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.rb.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.rs b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.rs similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.rs rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.rs diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.rs.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.rs.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.rs.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.rs.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.scss b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.scss similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.scss rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.scss diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.scss.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.scss.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.scss.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.scss.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.scss.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.scss.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.scss.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.scss.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.sh b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.sh similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.sh rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.sh diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.sh.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.sh.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.sh.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.sh.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.sh.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.sh.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.sh.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.sh.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.shader b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.shader similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.shader rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.shader diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.shader.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.shader.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.shader.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.shader.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.shader.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.shader.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.shader.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.shader.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.sql b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.sql similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.sql rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.sql diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.sql.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.sql.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.sql.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.sql.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.swift b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.swift similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.swift rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.swift diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.swift.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.swift.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.swift.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.swift.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.swift.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.swift.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.swift.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.swift.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.ts b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.ts similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.ts rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.ts diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.ts.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.ts.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.ts.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.ts.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.ts.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.ts.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.ts.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.ts.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.vb b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.vb similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.vb rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.vb diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.vb.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.vb.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.vb.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.vb.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.vb.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.vb.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.vb.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.vb.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.xml b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.xml similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.xml rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.xml diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.xml.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.xml.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.xml.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.xml.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.xml.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.xml.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.xml.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.xml.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.yaml b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.yaml similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.yaml rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.yaml diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.yaml.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.yaml.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.yaml.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.yaml.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.yaml.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.yaml.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test.yaml.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test.yaml.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test2.pl b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test2.pl similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test2.pl rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test2.pl diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test2.pl.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test2.pl.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test2.pl.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test2.pl.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test2.pl.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test2.pl.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test2.pl.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test2.pl.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test6916.js b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test6916.js similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test6916.js rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test6916.js diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test6916.js.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test6916.js.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/test6916.js.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/test6916.js.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/tsconfig.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/tsconfig.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/tsconfig.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/tsconfig.json diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/tsconfig.json.result b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/tsconfig.json.result similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/tsconfig.json.result rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/tsconfig.json.result diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/tsconfig.json.result.patch b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/tsconfig.json.result.patch similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tests/tsconfig.json.result.patch rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tests/tsconfig.json.result.patch diff --git a/org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tsconfig.json b/org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tsconfig.json similarity index 100% rename from org.eclipse.tm4e.core.tests/src/test/resources/test-cases/themes/tsconfig.json rename to org.eclipse.tm4e.core.tests/src/main/resources/test-cases/themes/tsconfig.json diff --git a/org.eclipse.tm4e.core/.classpath b/org.eclipse.tm4e.core/.classpath index 48fdbaaa9..3aa82bf3a 100644 --- a/org.eclipse.tm4e.core/.classpath +++ b/org.eclipse.tm4e.core/.classpath @@ -1,36 +1,40 @@ - + - - + + - + + - + + + + + - + - + + - + - + - - diff --git a/org.eclipse.tm4e.core/.gitignore b/org.eclipse.tm4e.core/.gitignore deleted file mode 100644 index 934e0e06f..000000000 --- a/org.eclipse.tm4e.core/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/bin -/target diff --git a/org.eclipse.tm4e.core/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.tm4e.core/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..6b99f88fc --- /dev/null +++ b/org.eclipse.tm4e.core/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,518 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.APILeak=warning +org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning +org.eclipse.jdt.core.compiler.problem.fallthroughCase=info +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=info +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=info +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=enabled +org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=11 +org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false +org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false +org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter=0 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type=49 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assertion_message=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0 +org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_record_components=16 +org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_type_annotations=0 +org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0 +org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch=0 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_constructor=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false +org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true +org.eclipse.jdt.core.formatter.comment.format_block_comments=false +org.eclipse.jdt.core.formatter.comment.format_header=true +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.indent_tag_description=false +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=120 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_not_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false +org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.text_block_indentation=0 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false +org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true +org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true +org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true +org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true +org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/org.eclipse.tm4e.core/META-INF/MANIFEST.MF b/org.eclipse.tm4e.core/META-INF/MANIFEST.MF index 41cdec9dd..4f1295259 100644 --- a/org.eclipse.tm4e.core/META-INF/MANIFEST.MF +++ b/org.eclipse.tm4e.core/META-INF/MANIFEST.MF @@ -4,12 +4,14 @@ Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-Localization: plugin Bundle-SymbolicName: org.eclipse.tm4e.core -Bundle-Version: 0.4.3.qualifier +Bundle-Version: 0.4.4.qualifier Require-Bundle: org.apache.batik.css;bundle-version="1.9.1";resolution:=optional, org.apache.batik.util;bundle-version="1.9.1";resolution:=optional, - com.google.gson;resolution:=optional, - org.jcodings;bundle-version="1.0.18", - org.joni;bundle-version="2.1.11" + com.google.gson, + com.google.guava;bundle-version="30.1.0", + org.jcodings;bundle-version="1.0.57", + org.joni;bundle-version="2.1.43", + org.yaml.snakeyaml;bundle-version="1.27.0" Import-Package: org.w3c.css.sac;resolution:=optional, org.w3c.css.sac.helpers;resolution:=optional, org.w3c.dom.css @@ -17,11 +19,10 @@ Bundle-RequiredExecutionEnvironment: JavaSE-11 Export-Package: org.eclipse.tm4e.core, org.eclipse.tm4e.core.grammar, org.eclipse.tm4e.core.internal.grammar;x-friends:="org.eclipse.tm4e.core.tests", - org.eclipse.tm4e.core.internal.grammars;x-friends:="org.eclipse.tm4e.core.tests", org.eclipse.tm4e.core.internal.matcher;x-friends:="org.eclipse.tm4e.core.tests", + org.eclipse.tm4e.core.internal.theme;x-friends:="org.eclipse.tm4e.core.tests", org.eclipse.tm4e.core.internal.theme.reader;x-friends:="org.eclipse.tm4e.core.tests", - org.eclipse.tm4e.core.internal.types;x-internal:=true, - org.eclipse.tm4e.core.internal.utils;x-friends:="org.eclipse.tm4e.core.tests", + org.eclipse.tm4e.core.internal.utils;x-friends:="org.eclipse.tm4e.core.tests,org.eclipse.tm4e.ui", org.eclipse.tm4e.core.model, org.eclipse.tm4e.core.registry, org.eclipse.tm4e.core.theme, diff --git a/org.eclipse.tm4e.core/build.properties b/org.eclipse.tm4e.core/build.properties index 065c68847..0a9f3a653 100644 --- a/org.eclipse.tm4e.core/build.properties +++ b/org.eclipse.tm4e.core/build.properties @@ -4,3 +4,9 @@ bin.includes = META-INF/,\ .,\ plugin.properties,\ about.html + +# https://codeiseasy.wordpress.com/2013/03/08/tycho-and-jdt-null-analysis/ +# JDT Null Analysis for Eclipse +additional.bundles = org.eclipse.jdt.annotation +# JDT Null Analysis types for Tycho +jars.extra.classpath = platform:/plugin/org.eclipse.jdt.annotation diff --git a/org.eclipse.tm4e.core/pom.xml b/org.eclipse.tm4e.core/pom.xml index c882d2ab5..47031f2fa 100644 --- a/org.eclipse.tm4e.core/pom.xml +++ b/org.eclipse.tm4e.core/pom.xml @@ -1,11 +1,73 @@ - - 4.0.0 - org.eclipse.tm4e.core - eclipse-plugin - 0.4.3-SNAPSHOT - - org.eclipse - org.eclipse.tm4e - 0.3.2-SNAPSHOT - + + 4.0.0 + org.eclipse.tm4e.core + eclipse-plugin + 0.4.4-SNAPSHOT + + org.eclipse + org.eclipse.tm4e + 0.3.2-SNAPSHOT + + + + + benchmark + + + benchmarkClass + + + + + + + net.officefloor.maven + tycho-shade-maven-plugin + 3.40.0 + + + shade + pre-integration-test + + shade + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.0.0 + + + integration-test + + exec + + + java + + + -Xms2048M + -Xmx2048M + -XX:+UseG1GC + + + -Xlog:gc:stderr + + -Dfile.encoding=UTF-8 + + -cp + ${project.build.directory}/${project.artifactId}-${project.version}-tychoshade.jar;${project.build.directory}/test-classes + ${benchmarkClass} + + + + + + + + + diff --git a/org.eclipse.tm4e.core/src/benchmark/BENCHMARK.md b/org.eclipse.tm4e.core/src/benchmark/BENCHMARK.md new file mode 100644 index 000000000..1f5a1d6bc --- /dev/null +++ b/org.eclipse.tm4e.core/src/benchmark/BENCHMARK.md @@ -0,0 +1,74 @@ +# TM4E Core Benchmarks + +## GrammarBenchmark + +The [GrammarBenchmark](../test/java/org/eclipse/tm4e/core/benchmark/GrammarBenchmark.java) measures how long it takes to tokenize a given source file using the +**[Grammar](../org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/Grammar.java)#tokenizeLine()** +method and how much memory is allocated on the JVM heap to do so. As test source file the +[GrammarBenchmark.JavaFile.txt](../test/resources/org/eclipse/tm4e/core/benchmark/GrammarBenchmark.JavaFile.txt) is used. + +The benchmark executes multiple rounds. In the beginning warm-up rounds are executed to get the JIT compiler activated. +The results of these rounds should be ignored. + +Each round is executed sequentially in a new thread. This gives the OS the opportunity, that in case for the first round an over-utilized core was chosen, to +select a better core to execute the new thread of the next benchmark round. + +The output will look something like this: +```yaml +[0.047s][info][gc] Using G1 +Source Code chars: 36.385 +Source Code lines: 901 +JVM Vendor: ojdkbuild +JVM Version: 11.0.14 +JVM Inital Heap: 2048.00 MB +JVM Maximum Heap: 2048.00 MB +JVM Args: -Xms2048M -Xmx2048M -XX:+UseG1GC -Xlog:gc:stderr -Dfile.encoding=UTF-8 +-------------------------------- +Warmup Rounds: 3 +Benchmark Rounds: 3 +Operations per Benchmark Round: 50 +-------------------------------- +warm-up 1/3... +#[1.626s][info][gc] GC(0) Pause Young (Normal) (G1 Evacuation Pause) 102M->3M(2048M) 4.692ms +#[6.155s][info][gc] GC(1) Pause Young (Normal) (G1 Evacuation Pause) 690M->3M(2048M) 3.132ms +#[10.557s][info][gc] GC(2) Pause Young (Normal) (G1 Evacuation Pause) 719M->3M(2048M) 2.788ms +#[15.228s][info][gc] GC(3) Pause Young (Normal) (G1 Evacuation Pause) 761M->3M(2048M) 2.957ms +#[20.160s][info][gc] GC(4) Pause Young (Normal) (G1 Evacuation Pause) 804M->3M(2048M) 2.743ms +#[25.590s][info][gc] GC(5) Pause Young (Normal) (G1 Evacuation Pause) 882M->3M(2048M) 2.632ms + -> result: 28307 ms/round | 529.90 ops/s | 113.23 ms/op +warm-up 2/3... +#[31.646s][info][gc] GC(6) Pause Young (Normal) (G1 Evacuation Pause) 987M->3M(2048M) 2.683ms +#[38.579s][info][gc] GC(7) Pause Young (Normal) (G1 Evacuation Pause) 1129M->3M(2048M) 2.927ms +#[46.106s][info][gc] GC(8) Pause Young (Normal) (G1 Evacuation Pause) 1227M->3M(2048M) 2.872ms +#[53.542s][info][gc] GC(9) Pause Young (Normal) (G1 Evacuation Pause) 1227M->3M(2048M) 2.727ms + -> result: 27172 ms/round | 552.04 ops/s | 108.69 ms/op +warm-up 3/3... +#[61.026s][info][gc] GC(10) Pause Young (Normal) (G1 Evacuation Pause) 1227M->3M(2048M) 3.225ms +#[68.556s][info][gc] GC(11) Pause Young (Normal) (G1 Evacuation Pause) 1227M->3M(2048M) 2.938ms +#[76.021s][info][gc] GC(12) Pause Young (Normal) (G1 Evacuation Pause) 1227M->3M(2048M) 2.766ms + -> result: 27129 ms/round | 552.91 ops/s | 108.52 ms/op +-------------------------------- +benchmark 1/3... +#[83.000s][info][gc] GC(13) Pause Full (System.gc()) 1139M->3M(2048M) 9.200ms +#[84.020s][info][gc] GC(14) Pause Full (System.gc()) 3M->3M(2048M) 6.465ms + -> result: 5315 ms/round | 564.44 ops/s | 106.30 ms/op | 17.73 MB/op +benchmark 2/3... +#[90.352s][info][gc] GC(15) Pause Full (System.gc()) 889M->3M(2048M) 8.125ms +#[91.361s][info][gc] GC(16) Pause Full (System.gc()) 3M->3M(2048M) 5.792ms + -> result: 5208 ms/round | 576.04 ops/s | 104.16 ms/op | 17.73 MB/op +benchmark 3/3... +#[97.590s][info][gc] GC(17) Pause Full (System.gc()) 889M->3M(2048M) 7.367ms +#[98.604s][info][gc] GC(18) Pause Full (System.gc()) 3M->3M(2048M) 6.515ms + -> result: 5202 ms/round | 576.70 ops/s | 104.04 ms/op | 17.73 MB/op +DONE. +``` + +The results of the three benchmark rounds show that it was possible to parse the whole source file 564.44 to 576.70 times per second.\ +One time parsing of the source file took 104.04 to 106.30 ms and allocated 17.73MB of temporary objects on the JVM heap. + +### How to run the benchmark +To run the benchmark execute the `run-grammar-benchmark.sh` or `run-grammar-benchmark.cmd` from a command line window. + +You can also run the [GrammarBenchmark](../test/java/org/eclipse/tm4e/core/benchmark/GrammarBenchmark.java) from within Eclipse via +`Run As -> Java Application` for development/debugging/testing purposes. However you need to add these VM arguments to the launch configuration: +`-Xms2048M -Xmx2048M -XX:+UseG1GC -Xlog:gc:stderr -Dfile.encoding=UTF-8`. Don't rely on the results when launched like this. diff --git a/org.eclipse.tm4e.core/src/benchmark/run-grammar-benchmark.cmd b/org.eclipse.tm4e.core/src/benchmark/run-grammar-benchmark.cmd new file mode 100644 index 000000000..b4f2ecfb4 --- /dev/null +++ b/org.eclipse.tm4e.core/src/benchmark/run-grammar-benchmark.cmd @@ -0,0 +1,21 @@ +@echo off +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:: Copyright (c) 2022 Sebatian Thomschke and others. +:: All rights reserved. This program and the accompanying materials +:: are made available under the terms of the Eclipse Public License v1.0 +:: which accompanies this distribution, and is available at +:: http://www.eclipse.org/legal/epl-v10.html +:: +:: Contributors: +:: Sebatian Thomschke - Initial API and implementation +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + +setlocal + +cd /D "%~dp0..\..\.." + +mvn clean verify ^ + -pl target-platform,org.eclipse.tm4e.core ^ + -Djgit.dirtyWorkingTree=warning ^ + -DskipTests ^ + -DbenchmarkClass=org.eclipse.tm4e.core.benchmark.GrammarBenchmark diff --git a/org.eclipse.tm4e.core/src/benchmark/run-grammar-benchmark.sh b/org.eclipse.tm4e.core/src/benchmark/run-grammar-benchmark.sh new file mode 100644 index 000000000..01c199ad4 --- /dev/null +++ b/org.eclipse.tm4e.core/src/benchmark/run-grammar-benchmark.sh @@ -0,0 +1,19 @@ +#!/bin/bash +############################################################################### +# Copyright (c) 2022 Sebatian Thomschke and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Sebatian Thomschke - Initial API and implementation +############################################################################### + +cd "$(dirname "$0")/../../.." + +mvn clean verify \ + -pl target-platform,org.eclipse.tm4e.core \ + -Djgit.dirtyWorkingTree=warning \ + -DskipTests \ + -DbenchmarkClass=org.eclipse.tm4e.core.benchmark.GrammarBenchmark diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/TMException.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/TMException.java index e9ff82962..dcafe20ae 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/TMException.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/TMException.java @@ -1,29 +1,29 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core; - -/** - * TextMate exception. - * - */ -public class TMException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - public TMException(String message) { - super(message); - } - - public TMException(String message, Throwable cause) { - super(message, cause); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core; + +/** + * TextMate exception. + * + */ +public class TMException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public TMException(final String message) { + super(message); + } + + public TMException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/GrammarHelper.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/GrammarHelper.java deleted file mode 100644 index 316199566..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/GrammarHelper.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/Microsoft/vscode-textmate/ - * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. - * Initial license: MIT - * - * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.grammar; - -import java.util.Map; - -import org.eclipse.tm4e.core.internal.grammar.Grammar; -import org.eclipse.tm4e.core.internal.oniguruma.OnigString; -import org.eclipse.tm4e.core.internal.types.IRawGrammar; -import org.eclipse.tm4e.core.theme.IThemeProvider; - -public class GrammarHelper { - - private GrammarHelper() { - // methods should be accessed statically - } - - public static IGrammar createGrammar(IRawGrammar grammar, int initialLanguage, - Map embeddedLanguages, IGrammarRepository repository, IThemeProvider themeProvider) { - return new Grammar(grammar, initialLanguage, embeddedLanguages, repository, themeProvider); - } - - public static OnigString createOnigString(String str) { - return new OnigString(str); - } - -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/IGrammar.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/IGrammar.java index bff5be455..f9ddaf457 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/IGrammar.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/IGrammar.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,45 +11,49 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java */ package org.eclipse.tm4e.core.grammar; import java.util.Collection; +import org.eclipse.jdt.annotation.Nullable; + /** * TextMate grammar API. - * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/main.ts + * + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/main.ts * */ public interface IGrammar { /** * Returns the name of the grammar. - * + * * @return the name of the grammar. */ + @Nullable String getName(); /** * Returns the scope name of the grammar. - * + * * @return the scope name of the grammar. */ String getScopeName(); /** * Returns the supported file types and null otherwise. - * + * * @return the supported file types and null otherwise. */ Collection getFileTypes(); /** * Tokenize `lineText`. - * + * * @param lineText * the line text to tokenize. * @return the result of the tokenization. @@ -58,14 +62,14 @@ public interface IGrammar { /** * Tokenize `lineText` using previous line state `prevState`. - * + * * @param lineText * the line text to tokenize. * @param prevState * previous line state. * @return the result of the tokenization. */ - ITokenizeLineResult tokenizeLine(String lineText, StackElement prevState); + ITokenizeLineResult tokenizeLine(String lineText, @Nullable IStackElement prevState); /** * Tokenize `lineText` using previous line state `prevState`. @@ -78,7 +82,7 @@ public interface IGrammar { * e.g. for getting the languageId: `(metadata & MetadataConsts.LANGUAGEID_MASK) >>> MetadataConsts.LANGUAGEID_OFFSET` */ ITokenizeLineResult2 tokenizeLine2(String lineText); - + /** * Tokenize `lineText` using previous line state `prevState`. * The result contains the tokens in binary format, resolved with the following information: @@ -89,6 +93,6 @@ public interface IGrammar { * - background color * e.g. for getting the languageId: `(metadata & MetadataConsts.LANGUAGEID_MASK) >>> MetadataConsts.LANGUAGEID_OFFSET` */ - ITokenizeLineResult2 tokenizeLine2(String lineText, StackElement prevState); - + ITokenizeLineResult2 tokenizeLine2(String lineText, @Nullable IStackElement prevState); + } diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/IStackElement.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/IStackElement.java new file mode 100644 index 000000000..fb7143d6d --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/IStackElement.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Initial code from https://github.com/Microsoft/vscode-textmate/ + * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. + * Initial license: MIT + * + * Contributors: + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.grammar; + +import org.eclipse.tm4e.core.internal.grammar.StackElement; + +/** + * Represents a "pushed" state on the stack (as a linked list element). + * + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/main.ts + */ +public interface IStackElement { + IStackElement INITIAL = StackElement.NULL; + + int getDepth(); +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/IToken.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/IToken.java index 810402f85..1cfef609e 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/IToken.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/IToken.java @@ -13,19 +13,19 @@ * Contributors: * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.grammar; - -import java.util.List; - -public interface IToken { - - int getStartIndex(); - - void setStartIndex(int startIndex); - - int getEndIndex(); - - List getScopes(); - -} + */ +package org.eclipse.tm4e.core.grammar; + +import java.util.List; + +public interface IToken { + + int getStartIndex(); + + void setStartIndex(int startIndex); + + int getEndIndex(); + + List getScopes(); + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/ITokenizeLineResult.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/ITokenizeLineResult.java index 9312a1221..5e51122fe 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/ITokenizeLineResult.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/ITokenizeLineResult.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,25 +11,25 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.grammar; - -/** - * Result of the line tokenization API. - * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/main.ts - */ -public interface ITokenizeLineResult { - - IToken[] getTokens(); - - /** - * Returns the `prevState` to be passed on to the next line tokenization. - * - * @return the `prevState` to be passed on to the next line tokenization. - */ - StackElement getRuleStack(); - -} + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.grammar; + +/** + * Result of the line tokenization API. + * + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/main.ts + */ +public interface ITokenizeLineResult { + + IToken[] getTokens(); + + /** + * Returns the `prevState` to be passed on to the next line tokenization. + * + * @return the `prevState` to be passed on to the next line tokenization. + */ + IStackElement getRuleStack(); +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/ITokenizeLineResult2.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/ITokenizeLineResult2.java index 4b57ca3de..3dce2c5dc 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/ITokenizeLineResult2.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/ITokenizeLineResult2.java @@ -19,7 +19,8 @@ /** * Result of the line tokenization2 API. * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/main.ts + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/main.ts */ public interface ITokenizeLineResult2 { @@ -32,9 +33,8 @@ public interface ITokenizeLineResult2 { /** * Returns the `prevState` to be passed on to the next line tokenization. - * + * * @return the `prevState` to be passed on to the next line tokenization. */ - StackElement getRuleStack(); - + IStackElement getRuleStack(); } diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/Injection.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/Injection.java deleted file mode 100644 index 487a0eea5..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/Injection.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/Microsoft/vscode-textmate/ - * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. - * Initial license: MIT - * - * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.grammar; - -import java.util.List; -import java.util.function.Predicate; - -import org.eclipse.tm4e.core.internal.types.IRawGrammar; - -public class Injection { - - private final Predicate> matcher; - public final int priority; // -1 | 0 | 1; // 0 is the default. -1 for 'L' and 1 for 'R' - public final int ruleId; - public final IRawGrammar grammar; - - public Injection(Predicate> matcher, int ruleId, IRawGrammar grammar, int priority) { - this.matcher = matcher; - this.ruleId = ruleId; - this.grammar = grammar; - this.priority = priority; - } - - public boolean match(List states) { - return matcher.test(states); - } -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/StackElement.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/StackElement.java deleted file mode 100644 index 56946a409..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/StackElement.java +++ /dev/null @@ -1,176 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/Microsoft/vscode-textmate/ - * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. - * Initial license: MIT - * - * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.grammar; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -import org.eclipse.tm4e.core.internal.grammar.ScopeListElement; -import org.eclipse.tm4e.core.internal.rule.IRuleRegistry; -import org.eclipse.tm4e.core.internal.rule.Rule; - -/** - * Represents a "pushed" state on the stack (as a linked list element). - * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/grammar.ts - * - */ -public class StackElement { - - public static final StackElement NULL = new StackElement(null, 0, 0, null, null, null); - - /** - * The position on the current line where this state was pushed. - * This is relevant only while tokenizing a line, to detect endless loops. - * Its value is meaningless across lines. - */ - private int enterPosition; - - /** - * The previous state on the stack (or null for the root state). - */ - public final StackElement parent; - /** - * The depth of the stack. - */ - public final int depth; - - /** - * The state (rule) that this element represents. - */ - public final int ruleId; - /** - * The "pop" (end) condition for this state in case that it was dynamically generated through captured text. - */ - public final String endRule; - /** - * The list of scopes containing the "name" for this state. - */ - public final ScopeListElement nameScopesList; - /** - * The list of scopes containing the "contentName" (besides "name") for this state. - * This list **must** contain as an element `scopeName`. - */ - public final ScopeListElement contentNameScopesList; - - public StackElement(StackElement parent, int ruleId, int enterPos, String endRule, ScopeListElement nameScopesList, ScopeListElement contentNameScopesList) { - this.parent = parent; - this.depth = (this.parent != null ? this.parent.depth + 1 : 1); - this.ruleId = ruleId; - this.enterPosition = enterPos; - this.endRule = endRule; - this.nameScopesList = nameScopesList; - this.contentNameScopesList = contentNameScopesList; - } - - /** - * A structural equals check. Does not take into account `scopes`. - */ - private static boolean structuralEquals(StackElement a, StackElement b) { - if (a == b) { - return true; - } - if (a == null || b == null) { - return false; - } - return a.depth == b.depth && a.ruleId == b.ruleId && !Objects.equals(a.endRule, b.endRule) && structuralEquals(a.parent, b.parent); - } - - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } - if (other == null) { - return false; - } - if (!(other instanceof StackElement)) { - return false; - } - StackElement stackElement = (StackElement)other; - return structuralEquals(this, stackElement) && this.contentNameScopesList.equals(stackElement.contentNameScopesList); - } - - @Override - public int hashCode() { - return Objects.hash(depth, ruleId, endRule, parent, contentNameScopesList); - } - - public void reset() { - StackElement el = this; - while (el != null) { - el.enterPosition = -1; - el = el.parent; - } - } - - public StackElement pop() { - return this.parent; - } - - public StackElement safePop() { - if (this.parent != null) { - return this.parent; - } - return this; - } - - public StackElement push(int ruleId, int enterPos, String endRule, ScopeListElement nameScopesList, ScopeListElement contentNameScopesList) { - return new StackElement(this, ruleId, enterPos, endRule, nameScopesList, contentNameScopesList); - } - - public int getEnterPos() { - return this.enterPosition; - } - - public Rule getRule(IRuleRegistry grammar) { - return grammar.getRule(this.ruleId); - } - - private void appendString(List res) { - if (this.parent != null) { - this.parent.appendString(res); - } - res.add('(' + Integer.toString(this.ruleId) + ')'); //, TODO-${this.nameScopesList}, TODO-${this.contentNameScopesList})`; - } - - @Override - public String toString() { - List r = new ArrayList<>(); - this.appendString(r); - return '[' + String.join(", ", r) + ']'; - } - - public StackElement setContentNameScopesList(ScopeListElement contentNameScopesList) { - if (this.contentNameScopesList.equals(contentNameScopesList)) { - return this; - } - return this.parent.push(this.ruleId, this.enterPosition, this.endRule, this.nameScopesList, contentNameScopesList); - } - - public StackElement setEndRule(String endRule) { - if (this.endRule != null && this.endRule.equals(endRule)) { - return this; - } - return new StackElement(this.parent, this.ruleId, this.enterPosition, endRule, this.nameScopesList, this.contentNameScopesList); - } - - public boolean hasSameRuleAs(StackElement other) { - return this.ruleId == other.ruleId; - } -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/package-info.java new file mode 100644 index 000000000..bfa17ddd6 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.core.grammar; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSDocumentHandler.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSDocumentHandler.java deleted file mode 100644 index 6ad596ba1..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSDocumentHandler.java +++ /dev/null @@ -1,155 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.css; - -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.tm4e.core.theme.IStyle; -import org.eclipse.tm4e.core.theme.RGB; -import org.eclipse.tm4e.core.theme.css.CSSStyle; -import org.w3c.css.sac.CSSException; -import org.w3c.css.sac.DocumentHandler; -import org.w3c.css.sac.InputSource; -import org.w3c.css.sac.LexicalUnit; -import org.w3c.css.sac.SACMediaList; -import org.w3c.css.sac.SelectorList; -import org.w3c.dom.css.CSSPrimitiveValue; -import org.w3c.dom.css.RGBColor; - -public class CSSDocumentHandler implements DocumentHandler { - - private final List list; - private CSSStyle currentStyle; - - public CSSDocumentHandler() { - list = new ArrayList<>(); - } - - @Override - public void comment(String arg0) throws CSSException { - - } - - @Override - public void endDocument(InputSource arg0) throws CSSException { - // TODO Auto-generated method stub - - } - - @Override - public void endFontFace() throws CSSException { - // TODO Auto-generated method stub - - } - - @Override - public void endMedia(SACMediaList arg0) throws CSSException { - // TODO Auto-generated method stub - - } - - @Override - public void endPage(String arg0, String arg1) throws CSSException { - // TODO Auto-generated method stub - - } - - @Override - public void endSelector(SelectorList selector) throws CSSException { - currentStyle = null; - } - - @Override - public void ignorableAtRule(String arg0) throws CSSException { - // TODO Auto-generated method stub - - } - - @Override - public void importStyle(String arg0, SACMediaList arg1, String arg2) throws CSSException { - // TODO Auto-generated method stub - - } - - @Override - public void namespaceDeclaration(String arg0, String arg1) throws CSSException { - // TODO Auto-generated method stub - - } - - @Override - public void property(String name, LexicalUnit value, boolean arg2) throws CSSException { - if (currentStyle != null) { - if ("color".equals(name)) { - currentStyle.setColor(createRGB(value)); - } else if ("background-color".equals(name)) { - currentStyle.setBackgroundColor(createRGB(value)); - } else if ("font-weight".equals(name)) { - currentStyle.setBold(value.getStringValue().toUpperCase().contains("BOLD")); - } else if ("font-style".equals(name)) { - currentStyle.setItalic(value.getStringValue().toUpperCase().contains("ITALIC")); - } - if ("text-decoration".equals(name)) { - String decoration = value.getStringValue().toUpperCase(); - if (decoration.contains("UNDERLINE")) { - currentStyle.setUnderline(true); - } - if (decoration.contains("LINE-THROUGH")) { - currentStyle.setStrikeThrough(true); - } - } - } - } - - private RGB createRGB(LexicalUnit value) { - RGBColor rgbColor = new RGBColorImpl(value); - int green = ((int) rgbColor.getGreen().getFloatValue(CSSPrimitiveValue.CSS_NUMBER)); - int red = ((int) rgbColor.getRed().getFloatValue(CSSPrimitiveValue.CSS_NUMBER)); - int blue = ((int) rgbColor.getBlue().getFloatValue(CSSPrimitiveValue.CSS_NUMBER)); - return new RGB(red, green, blue); - } - - @Override - public void startDocument(InputSource arg0) throws CSSException { - // TODO Auto-generated method stub - - } - - @Override - public void startFontFace() throws CSSException { - // TODO Auto-generated method stub - - } - - @Override - public void startMedia(SACMediaList arg0) throws CSSException { - // TODO Auto-generated method stub - - } - - @Override - public void startPage(String arg0, String arg1) throws CSSException { - // TODO Auto-generated method stub - - } - - @Override - public void startSelector(SelectorList selector) throws CSSException { - currentStyle = new CSSStyle(selector); - list.add(currentStyle); - } - - public List getList() { - return list; - } -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/BalancedBracketSelectors.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/BalancedBracketSelectors.java new file mode 100644 index 000000000..6c33439ae --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/BalancedBracketSelectors.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2022 Sebastian Thomschke and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Initial code from https://github.com/Microsoft/vscode-textmate/ + * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. + * Initial license: MIT + * + * Contributors: + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Sebastian Thomschke - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.grammar; + +import java.util.List; +import java.util.stream.Stream; + +import org.eclipse.tm4e.core.internal.matcher.Matcher; + +public class BalancedBracketSelectors { + private final Matcher>[] balancedBracketScopes; + private final Matcher>[] unbalancedBracketScopes; + + private boolean allowAny = false; + + BalancedBracketSelectors(final List balancedBracketScopes, final List unbalancedBracketScopes) { + this.balancedBracketScopes = balancedBracketScopes.stream() + .flatMap(selector -> { + if ("*".equals(selector)) { + this.allowAny = true; + return Stream.empty(); + } + return Matcher.createMatchers(selector).stream(); + }) + .map(m -> m.matcher).toArray(Matcher[]::new); + + this.unbalancedBracketScopes = unbalancedBracketScopes.stream() + .flatMap(selector -> Matcher.createMatchers(selector).stream()) + .map(m -> m.matcher).toArray(Matcher[]::new); + } + + boolean matchesAlways() { + return this.allowAny && this.unbalancedBracketScopes.length == 0; + } + + boolean matchesNever() { + return !this.allowAny && this.balancedBracketScopes.length == 0; + } + + boolean match(final List scopes) { + for (final var excluder : this.unbalancedBracketScopes) { + if (excluder.matches(scopes)) { + return false; + } + } + + for (final var includer : this.balancedBracketScopes) { + if (includer.matches(scopes)) { + return true; + } + } + return this.allowAny; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/Grammar.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/Grammar.java index 4a3f98552..6d6fc1e7e 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/Grammar.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/Grammar.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,201 +11,274 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - * - Fabio Zadrozny - Not adding '\n' on tokenize if it already finished with '\n' + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + * - Fabio Zadrozny - Not adding '\n' on tokenize if it already finished with '\n' */ package org.eclipse.tm4e.core.internal.grammar; +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; +import java.util.Objects; import java.util.function.IntFunction; -import org.eclipse.tm4e.core.grammar.GrammarHelper; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tm4e.core.grammar.IGrammar; -import org.eclipse.tm4e.core.grammar.IGrammarRepository; +import org.eclipse.tm4e.core.grammar.IStackElement; import org.eclipse.tm4e.core.grammar.ITokenizeLineResult; import org.eclipse.tm4e.core.grammar.ITokenizeLineResult2; -import org.eclipse.tm4e.core.grammar.Injection; -import org.eclipse.tm4e.core.grammar.StackElement; -import org.eclipse.tm4e.core.internal.grammar.parser.Raw; import org.eclipse.tm4e.core.internal.matcher.Matcher; -import org.eclipse.tm4e.core.internal.matcher.MatcherWithPriority; import org.eclipse.tm4e.core.internal.oniguruma.OnigString; +import org.eclipse.tm4e.core.internal.registry.IGrammarRepository; import org.eclipse.tm4e.core.internal.rule.IRuleFactoryHelper; import org.eclipse.tm4e.core.internal.rule.Rule; import org.eclipse.tm4e.core.internal.rule.RuleFactory; +import org.eclipse.tm4e.core.internal.theme.IThemeProvider; import org.eclipse.tm4e.core.internal.types.IRawGrammar; import org.eclipse.tm4e.core.internal.types.IRawRepository; import org.eclipse.tm4e.core.internal.types.IRawRule; -import org.eclipse.tm4e.core.theme.IThemeProvider; -import org.eclipse.tm4e.core.theme.ThemeTrieElementRule; /** * TextMate grammar implementation. * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/grammar.ts - * + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/grammar.ts */ -public class Grammar implements IGrammar, IRuleFactoryHelper { +public final class Grammar implements IGrammar, IRuleFactoryHelper { + + private static final Logger LOGGER = System.getLogger(Grammar.class.getName()); + + private final String scopeName; - private int rootId; - private int lastRuleId; - private final Map ruleId2desc; - private final Map includedGrammars; + private int rootId = -1; + private int lastRuleId = 0; + private final Map ruleId2desc = new HashMap<>(); + private final Map includedGrammars = new HashMap<>(); private final IGrammarRepository grammarRepository; private final IRawGrammar grammar; + + @Nullable private List injections; private final ScopeMetadataProvider scopeMetadataProvider; - - public Grammar(IRawGrammar grammar, int initialLanguage, Map embeddedLanguages, - IGrammarRepository grammarRepository, IThemeProvider themeProvider) { + private final List tokenTypeMatchers = new ArrayList<>(); + + @Nullable + private final BalancedBracketSelectors balancedBracketSelectors; + + public Grammar( + final String scopeName, + final IRawGrammar grammar, + final int initialLanguage, + @Nullable final Map embeddedLanguages, + @Nullable final Map tokenTypes, + @Nullable final BalancedBracketSelectors balancedBracketSelectors, + final IGrammarRepository grammarRepository, + final IThemeProvider themeProvider) { + this.scopeName = scopeName; this.scopeMetadataProvider = new ScopeMetadataProvider(initialLanguage, themeProvider, embeddedLanguages); - this.rootId = -1; - this.lastRuleId = 0; - this.includedGrammars = new HashMap<>(); + this.balancedBracketSelectors = balancedBracketSelectors; this.grammarRepository = grammarRepository; this.grammar = initGrammar(grammar, null); - this.ruleId2desc = new HashMap<>(); - this.injections = null; + + if (tokenTypes != null) { + for (final var entry : tokenTypes.entrySet()) { + final var selector = entry.getKey(); + final var type = entry.getValue().intValue(); + for (final var matcher : Matcher.createMatchers(selector)) { + tokenTypeMatchers.add(new TokenTypeMatcher() { + @Override + public int getType() { + return type; + } + + @Override + public Matcher> getMatcher() { + return matcher.matcher; + } + }); + } + } + } } public void onDidChangeTheme() { this.scopeMetadataProvider.onDidChangeTheme(); } - public ScopeMetadata getMetadataForScope(String scope) { + ScopeMetadata getMetadataForScope(final String scope) { return this.scopeMetadataProvider.getMetadataForScope(scope); } - public List getInjections() { - if (this.injections == null) { - this.injections = new ArrayList<>(); + private void collectInjections(final List result, final String selector, final IRawRule rule, + final IRuleFactoryHelper ruleFactoryHelper, final IRawGrammar grammar) { + final var matchers = Matcher.createMatchers(selector); + final int ruleId = RuleFactory.getCompiledRuleId(rule, ruleFactoryHelper, this.grammar.getRepository()); + + for (final var matcher : matchers) { + result.add(new Injection(selector, matcher.matcher, ruleId, grammar, matcher.priority)); + } + } + + private List collectInjections() { + final var grammarRepository = new IGrammarRepository() { + @Override + public @Nullable IRawGrammar lookup(final String scopeName) { + if (Objects.equals(scopeName, Grammar.this.scopeName)) { + return Grammar.this.grammar; + } + return getExternalGrammar(scopeName, null); + } + + @Override + public @Nullable Collection injections(final String targetScope) { + return Grammar.this.grammarRepository.injections(targetScope); + } + }; + + final var dependencyProcessor = new ScopeDependencyProcessor(grammarRepository, this.scopeName); + // TODO: uncomment below to visit all scopes + // while (dependencyProcessor.queue.length > 0) { + // dependencyProcessor.processQueue(); + // } + + final var result = new ArrayList(); + + dependencyProcessor.seenFullScopeRequests.forEach((scopeName) -> { + final var grammar = grammarRepository.lookup(scopeName); + if (grammar == null) { + return; + } + // add injections from the current grammar - Map rawInjections = this.grammar.getInjections(); + final var rawInjections = grammar.getInjections(); if (rawInjections != null) { - for (Entry injection : rawInjections.entrySet()) { - String expression = injection.getKey(); - IRawRule rule = injection.getValue(); - collectInjections(this.injections, expression, rule, this, this.grammar); + for (final var e : rawInjections.entrySet()) { + collectInjections(result, e.getKey(), e.getValue(), this, grammar); } } // add injection grammars contributed for the current scope - if (this.grammarRepository != null) { - Collection injectionScopeNames = this.grammarRepository - .injections(this.grammar.getScopeName()); - if (injectionScopeNames != null) { - injectionScopeNames.forEach(injectionScopeName -> { - IRawGrammar injectionGrammar = this.getExternalGrammar(injectionScopeName); - if (injectionGrammar != null) { - String selector = injectionGrammar.getInjectionSelector(); - if (selector != null) { - collectInjections(this.injections, selector, (IRawRule) injectionGrammar, this, - injectionGrammar); - } + final var injectionScopeNames = this.grammarRepository.injections(scopeName); + if (injectionScopeNames != null) { + injectionScopeNames.forEach(injectionScopeName -> { + final var injectionGrammar = Grammar.this.getExternalGrammar(injectionScopeName, null); + if (injectionGrammar != null) { + final var selector = injectionGrammar.getInjectionSelector(); + if (selector != null) { + collectInjections(result, selector, injectionGrammar.toRawRule(), this, + injectionGrammar); } - }); - } + } + }); } - Collections.sort(this.injections, (i1, i2) -> i1.priority - i2.priority); // sort by priority - } - if (this.injections.isEmpty()) { - return this.injections; - } - return this.injections; + }); + + Collections.sort(result, (i1, i2) -> i1.priority - i2.priority); // sort by priority + + return result; } - private void collectInjections(List result, String selector, IRawRule rule, - IRuleFactoryHelper ruleFactoryHelper, IRawGrammar grammar) { - Collection>> matchers = Matcher.createMatchers(selector); - int ruleId = RuleFactory.getCompiledRuleId(rule, ruleFactoryHelper, grammar.getRepository()); + List getInjections() { + var injections = this.injections; + if (injections == null) { + injections = this.injections = this.collectInjections(); - for (MatcherWithPriority> matcher : matchers) { - result.add(new Injection(matcher.matcher, ruleId, grammar, matcher.priority)); + if (LOGGER.isLoggable(Level.TRACE) && !injections.isEmpty()) { + LOGGER.log(Level.TRACE, + "Grammar " + scopeName + " contains the following injections:"); + for (final var injection : injections) { + LOGGER.log(Level.TRACE, " - " + injection.debugSelector); + } + } } + return injections; } @Override - public Rule registerRule(IntFunction factory) { - int id = (++this.lastRuleId); - Rule result = factory.apply(id); + public T registerRule(final IntFunction factory) { + final int id = ++this.lastRuleId; + final @Nullable T result = factory.apply(id); this.ruleId2desc.put(id, result); return result; } @Override - public Rule getRule(int patternId) { - return this.ruleId2desc.get(patternId); - } - - public IRawGrammar getExternalGrammar(String scopeName) { - return getExternalGrammar(scopeName, null); + public Rule getRule(final int patternId) { + final var rule = this.ruleId2desc.get(patternId); + if (rule == null) { + throw new IndexOutOfBoundsException( + "No rule with index " + patternId + " found. Possible values: 0.." + this.ruleId2desc.size()); + } + return rule; } @Override - public IRawGrammar getExternalGrammar(String scopeName, IRawRepository repository) { + @Nullable + public IRawGrammar getExternalGrammar(final String scopeName, @Nullable final IRawRepository repository) { if (this.includedGrammars.containsKey(scopeName)) { return this.includedGrammars.get(scopeName); - } else if (this.grammarRepository != null) { - IRawGrammar rawIncludedGrammar = this.grammarRepository.lookup(scopeName); - if (rawIncludedGrammar != null) { - this.includedGrammars.put(scopeName, - initGrammar(rawIncludedGrammar, repository != null ? repository.getBase() : null)); - return this.includedGrammars.get(scopeName); - } + } + + final IRawGrammar rawIncludedGrammar = this.grammarRepository.lookup(scopeName); + if (rawIncludedGrammar != null) { + this.includedGrammars.put(scopeName, + initGrammar(rawIncludedGrammar, repository != null ? repository.getBase() : null)); + return this.includedGrammars.get(scopeName); } return null; } - private IRawGrammar initGrammar(IRawGrammar grammar, IRawRule base) { - grammar = clone(grammar); - if (grammar.getRepository() == null) { - ((Raw) grammar).setRepository(new Raw()); + private IRawGrammar initGrammar(IRawGrammar grammar, @Nullable final IRawRule base) { + grammar = grammar.deepClone(); + + final IRawRepository repo; + if (grammar.isRepositorySet()) { + repo = grammar.getRepository(); + } else { + repo = new RawRepository(); + grammar.setRepository(repo); } - Raw self = new Raw(); + + final var self = new RawRule(); self.setPatterns(grammar.getPatterns()); self.setName(grammar.getScopeName()); - grammar.getRepository().setSelf(self); - if (base != null) { - grammar.getRepository().setBase(base); - } else { - grammar.getRepository().setBase(grammar.getRepository().getSelf()); - } + repo.setSelf(self); + repo.setBase(base != null ? base : self); return grammar; } - private IRawGrammar clone(IRawGrammar grammar) { - return (IRawGrammar) ((Raw) grammar).clone(); - } - @Override - public ITokenizeLineResult tokenizeLine(String lineText) { + public ITokenizeLineResult tokenizeLine(final String lineText) { return tokenizeLine(lineText, null); } @Override - public ITokenizeLineResult tokenizeLine(String lineText, StackElement prevState) { - return tokenize(lineText, prevState, false); + public ITokenizeLineResult tokenizeLine(final String lineText, @Nullable final IStackElement prevState) { + return tokenize(lineText, (StackElement) prevState, false); } @Override - public ITokenizeLineResult2 tokenizeLine2(String lineText) { + public ITokenizeLineResult2 tokenizeLine2(final String lineText) { return tokenizeLine2(lineText, null); } @Override - public ITokenizeLineResult2 tokenizeLine2(String lineText, StackElement prevState) { - return tokenize(lineText, prevState, true); + public ITokenizeLineResult2 tokenizeLine2(final String lineText, @Nullable final IStackElement prevState) { + return tokenize(lineText, (StackElement) prevState, true); } @SuppressWarnings("unchecked") - private T tokenize(String lineText, StackElement prevState, boolean emitBinaryTokens) { + private T tokenize(String lineText, @Nullable StackElement prevState, final boolean emitBinaryTokens) { if (this.rootId == -1) { this.rootId = RuleFactory.getCompiledRuleId(this.grammar.getRepository().getSelf(), this, this.grammar.getRepository()); @@ -214,19 +287,22 @@ private T tokenize(String lineText, StackElement prevState, boolean emitBina boolean isFirstLine; if (prevState == null || prevState.equals(StackElement.NULL)) { isFirstLine = true; - ScopeMetadata rawDefaultMetadata = this.scopeMetadataProvider.getDefaultMetadata(); - ThemeTrieElementRule defaultTheme = rawDefaultMetadata.themeData.get(0); - int defaultMetadata = StackElementMetadata.set(0, rawDefaultMetadata.languageId, - rawDefaultMetadata.tokenType, defaultTheme.fontStyle, defaultTheme.foreground, + final var rawDefaultMetadata = this.scopeMetadataProvider.getDefaultMetadata(); + final var themeData = rawDefaultMetadata.themeData; + final var defaultTheme = themeData == null ? null : themeData.get(0); + final int defaultMetadata = StackElementMetadata.set(0, rawDefaultMetadata.languageId, + rawDefaultMetadata.tokenType, null, defaultTheme.fontStyle, defaultTheme.foreground, defaultTheme.background); - String rootScopeName = this.getRule(this.rootId).getName(null, null); - ScopeMetadata rawRootMetadata = this.scopeMetadataProvider.getMetadataForScope(rootScopeName); - int rootMetadata = ScopeListElement.mergeMetadata(defaultMetadata, null, rawRootMetadata); + final var rootRule = castNonNull(this.getRule(this.rootId)); + final var rootScopeName = rootRule.getName(null, null); + final var rawRootMetadata = this.scopeMetadataProvider.getMetadataForScope(rootScopeName); + final int rootMetadata = ScopeListElement.mergeMetadata(defaultMetadata, null, rawRootMetadata); - ScopeListElement scopeList = new ScopeListElement(null, rootScopeName, rootMetadata); + final ScopeListElement scopeList = new ScopeListElement(null, + rootScopeName == null ? "unknown" : rootScopeName, rootMetadata); - prevState = new StackElement(null, this.rootId, -1, null, scopeList, scopeList); + prevState = new StackElement(null, this.rootId, -1, -1, false, null, scopeList, scopeList); } else { isFirstLine = false; prevState.reset(); @@ -236,11 +312,11 @@ private T tokenize(String lineText, StackElement prevState, boolean emitBina // Only add \n if the passed lineText didn't have it. lineText += '\n'; } - OnigString onigLineText = GrammarHelper.createOnigString(lineText); - int lineLength = lineText.length(); - LineTokens lineTokens = new LineTokens(emitBinaryTokens, lineText); - StackElement nextState = LineTokenizer.tokenizeString(this, onigLineText, isFirstLine, 0, prevState, - lineTokens); + final var onigLineText = OnigString.of(lineText); + final int lineLength = lineText.length(); + final var lineTokens = new LineTokens(emitBinaryTokens, lineText, tokenTypeMatchers, balancedBracketSelectors); + final var nextState = LineTokenizer.tokenizeString(this, onigLineText, isFirstLine, 0, prevState, lineTokens, + true); if (emitBinaryTokens) { return (T) new TokenizeLineResult2(lineTokens.getBinaryResult(nextState, lineLength), nextState); @@ -249,18 +325,18 @@ private T tokenize(String lineText, StackElement prevState, boolean emitBina } @Override + @Nullable public String getName() { return grammar.getName(); } @Override public String getScopeName() { - return grammar.getScopeName(); + return scopeName; } @Override public Collection getFileTypes() { return grammar.getFileTypes(); } - } diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/Injection.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/Injection.java new file mode 100644 index 000000000..f6fc0bc13 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/Injection.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Initial code from https://github.com/Microsoft/vscode-textmate/ + * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. + * Initial license: MIT + * + * Contributors: + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.grammar; + +import java.util.List; + +import org.eclipse.tm4e.core.internal.matcher.Matcher; +import org.eclipse.tm4e.core.internal.types.IRawGrammar; + +final class Injection { + + final String debugSelector; + private final Matcher> matcher; + final int priority; // -1 | 0 | 1; // 0 is the default. -1 for 'L' and 1 for 'R' + final int ruleId; + final IRawGrammar grammar; + + Injection(final String debugSelector, final Matcher> matcher, final int ruleId, + final IRawGrammar grammar, final int priority) { + this.debugSelector = debugSelector; + this.matcher = matcher; + this.ruleId = ruleId; + this.grammar = grammar; + this.priority = priority; + } + + boolean matches(final List states) { + return matcher.matches(states); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/LineTokenizer.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/LineTokenizer.java index da70a91f9..41b8353f7 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/LineTokenizer.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/LineTokenizer.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,53 +11,70 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java */ package org.eclipse.tm4e.core.internal.grammar; +import static java.lang.System.Logger.Level.*; +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import java.lang.System.Logger; +import java.lang.System.Logger.Level; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.List; -import java.util.logging.Logger; - -import org.eclipse.tm4e.core.grammar.GrammarHelper; -import org.eclipse.tm4e.core.grammar.Injection; -import org.eclipse.tm4e.core.grammar.StackElement; -import org.eclipse.tm4e.core.internal.matcher.IMatchInjectionsResult; -import org.eclipse.tm4e.core.internal.matcher.IMatchResult; -import org.eclipse.tm4e.core.internal.oniguruma.IOnigCaptureIndex; -import org.eclipse.tm4e.core.internal.oniguruma.IOnigNextMatchResult; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.oniguruma.OnigCaptureIndex; +import org.eclipse.tm4e.core.internal.oniguruma.OnigNextMatchResult; import org.eclipse.tm4e.core.internal.oniguruma.OnigString; import org.eclipse.tm4e.core.internal.rule.BeginEndRule; import org.eclipse.tm4e.core.internal.rule.BeginWhileRule; import org.eclipse.tm4e.core.internal.rule.CaptureRule; -import org.eclipse.tm4e.core.internal.rule.ICompiledRule; +import org.eclipse.tm4e.core.internal.rule.CompiledRule; import org.eclipse.tm4e.core.internal.rule.MatchRule; import org.eclipse.tm4e.core.internal.rule.Rule; -class LineTokenizer { +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/grammar.ts + */ +final class LineTokenizer { + + private static final Logger LOGGER = System.getLogger(LineTokenizer.class.getName()); - private static final Logger LOGGER = Logger.getLogger(LineTokenizer.class.getName()); + private interface IMatchResult { + OnigCaptureIndex[] getCaptureIndices(); + + int getMatchedRuleId(); + } + + private interface IMatchInjectionsResult extends IMatchResult { + boolean isPriorityMatch(); + } - class WhileStack { + private static final class WhileStack { - public final StackElement stack; - public final BeginWhileRule rule; + private final StackElement stack; + private final BeginWhileRule rule; - public WhileStack(StackElement stack, BeginWhileRule rule) { + private WhileStack(final StackElement stack, final BeginWhileRule rule) { this.stack = stack; this.rule = rule; } } - class WhileCheckResult { + private static final class WhileCheckResult { - public final StackElement stack; - public final int linePos; - public final int anchorPosition; - public final boolean isFirstLine; + private final StackElement stack; + private final int linePos; + private final int anchorPosition; + private final boolean isFirstLine; - public WhileCheckResult(StackElement stack, int linePos, int anchorPosition, boolean isFirstLine) { + private WhileCheckResult(final StackElement stack, final int linePos, final int anchorPosition, + final boolean isFirstLine) { this.stack = stack; this.linePos = linePos; this.anchorPosition = anchorPosition; @@ -73,28 +90,28 @@ public WhileCheckResult(StackElement stack, int linePos, int anchorPosition, boo private final LineTokens lineTokens; private int anchorPosition = -1; private boolean stop; - private final int lineLength; - public LineTokenizer(Grammar grammar, OnigString lineText, boolean isFirstLine, int linePos, StackElement stack, - LineTokens lineTokens) { + private LineTokenizer(final Grammar grammar, final OnigString lineText, final boolean isFirstLine, + final int linePos, final StackElement stack, final LineTokens lineTokens) { this.grammar = grammar; this.lineText = lineText; - this.lineLength = lineText.utf8_value.length; this.isFirstLine = isFirstLine; this.linePos = linePos; this.stack = stack; this.lineTokens = lineTokens; } - public StackElement scan() { + private StackElement scan(final boolean checkWhileConditions) { stop = false; - WhileCheckResult whileCheckResult = checkWhileConditions(grammar, lineText, isFirstLine, linePos, stack, - lineTokens); - stack = whileCheckResult.stack; - linePos = whileCheckResult.linePos; - isFirstLine = whileCheckResult.isFirstLine; - anchorPosition = whileCheckResult.anchorPosition; + if (checkWhileConditions) { + final var whileCheckResult = checkWhileConditions(grammar, lineText, isFirstLine, linePos, stack, + lineTokens); + stack = whileCheckResult.stack; + linePos = whileCheckResult.linePos; + isFirstLine = whileCheckResult.isFirstLine; + anchorPosition = whileCheckResult.anchorPosition; + } while (!stop) { scanNext(); // potentially modifies linePos && anchorPosition @@ -104,69 +121,70 @@ public StackElement scan() { } private void scanNext() { - LOGGER.finest("@@scanNext: |" + lineText.string.replaceAll("\n", "\\n").substring(linePos) + '|'); + LOGGER.log(TRACE, () -> "@@scanNext: |" + lineText.string.replace("\n", "\\n").substring(linePos) + '|'); - IMatchResult r = matchRuleOrInjections(grammar, lineText, isFirstLine, linePos, stack, anchorPosition); + final IMatchResult r = matchRuleOrInjections(grammar, lineText, isFirstLine, linePos, stack, anchorPosition); if (r == null) { - LOGGER.finest(" no more matches."); + LOGGER.log(TRACE, " no more matches."); // No match - lineTokens.produce(stack, lineLength); + lineTokens.produce(stack, lineText.bytesCount); stop = true; return; } - IOnigCaptureIndex[] captureIndices = r.getCaptureIndices(); - int matchedRuleId = r.getMatchedRuleId(); + final OnigCaptureIndex[] captureIndices = r.getCaptureIndices(); + final int matchedRuleId = r.getMatchedRuleId(); - boolean hasAdvanced = (captureIndices != null && captureIndices.length > 0) - ? (captureIndices[0].getEnd() > linePos) - : false; + final boolean hasAdvanced = captureIndices.length > 0 && captureIndices[0].end > linePos; if (matchedRuleId == -1) { // We matched the `end` for this rule => pop it - BeginEndRule poppedRule = (BeginEndRule) stack.getRule(grammar); + final BeginEndRule poppedRule = (BeginEndRule) stack.getRule(grammar); /* * if (logger.isEnabled()) { logger.log(" popping " + poppedRule.debugName + * " - " + poppedRule.debugEndRegExp); } */ - lineTokens.produce(stack, captureIndices[0].getStart()); + lineTokens.produce(stack, captureIndices[0].start); stack = stack.setContentNameScopesList(stack.nameScopesList); handleCaptures(grammar, lineText, isFirstLine, stack, lineTokens, poppedRule.endCaptures, captureIndices); - lineTokens.produce(stack, captureIndices[0].getEnd()); + lineTokens.produce(stack, captureIndices[0].end); // pop - StackElement popped = stack; - stack = stack.pop(); + final var popped = stack; + stack = castNonNull(stack.pop()); + anchorPosition = popped.getAnchorPos(); if (!hasAdvanced && popped.getEnterPos() == linePos) { // Grammar pushed & popped a rule without advancing - LOGGER.info("[1] - Grammar is in an endless loop - Grammar pushed & popped a rule without advancing"); + LOGGER.log(INFO, + "[1] - Grammar is in an endless loop - Grammar pushed & popped a rule without advancing"); // See https://github.com/Microsoft/vscode-textmate/issues/12 // Let's assume this was a mistake by the grammar author and the // intent was to continue in this state stack = popped; - lineTokens.produce(stack, lineLength); + lineTokens.produce(stack, lineText.bytesCount); stop = true; return; } - } else if (captureIndices != null && captureIndices.length > 0) { + } else if (captureIndices.length > 0) { // We matched a rule! - Rule rule = grammar.getRule(matchedRuleId); + final Rule rule = grammar.getRule(matchedRuleId); - lineTokens.produce(stack, captureIndices[0].getStart()); + lineTokens.produce(stack, captureIndices[0].start); - StackElement beforePush = stack; + final StackElement beforePush = stack; // push it on the stack rule - String scopeName = rule.getName(lineText.string, captureIndices); - ScopeListElement nameScopesList = stack.contentNameScopesList.push(grammar, scopeName); - stack = stack.push(matchedRuleId, linePos, null, nameScopesList, nameScopesList); + final String scopeName = rule.getName(lineText.string, captureIndices); + final ScopeListElement nameScopesList = stack.contentNameScopesList.push(grammar, scopeName); + stack = stack.push(matchedRuleId, linePos, anchorPosition, + captureIndices[0].end == lineText.bytesCount, null, nameScopesList, nameScopesList); if (rule instanceof BeginEndRule) { - BeginEndRule pushedRule = (BeginEndRule) rule; + final BeginEndRule pushedRule = (BeginEndRule) rule; // if (IN_DEBUG_MODE) { // console.log(' pushing ' + pushedRule.debugName + ' - ' + @@ -175,11 +193,11 @@ private void scanNext() { handleCaptures(grammar, lineText, isFirstLine, stack, lineTokens, pushedRule.beginCaptures, captureIndices); - lineTokens.produce(stack, captureIndices[0].getEnd()); - anchorPosition = captureIndices[0].getEnd(); + lineTokens.produce(stack, captureIndices[0].end); + anchorPosition = captureIndices[0].end; - String contentName = pushedRule.getContentName(lineText.string, captureIndices); - ScopeListElement contentNameScopesList = nameScopesList.push(grammar, contentName); + final String contentName = pushedRule.getContentName(lineText.string, captureIndices); + final ScopeListElement contentNameScopesList = nameScopesList.push(grammar, contentName); stack = stack.setContentNameScopesList(contentNameScopesList); if (pushedRule.endHasBackReferences) { @@ -189,25 +207,26 @@ private void scanNext() { if (!hasAdvanced && beforePush.hasSameRuleAs(stack)) { // Grammar pushed the same rule without advancing - LOGGER.info("[2] - Grammar is in an endless loop - Grammar pushed the same rule without advancing"); - stack = stack.pop(); - lineTokens.produce(stack, lineLength); + LOGGER.log(INFO, + "[2] - Grammar is in an endless loop - Grammar pushed the same rule without advancing"); + stack = castNonNull(stack.pop()); + lineTokens.produce(stack, lineText.bytesCount); stop = true; return; } } else if (rule instanceof BeginWhileRule) { - BeginWhileRule pushedRule = (BeginWhileRule) rule; + final BeginWhileRule pushedRule = (BeginWhileRule) rule; // if (IN_DEBUG_MODE) { // console.log(' pushing ' + pushedRule.debugName); // } handleCaptures(grammar, lineText, isFirstLine, stack, lineTokens, pushedRule.beginCaptures, captureIndices); - lineTokens.produce(stack, captureIndices[0].getEnd()); - anchorPosition = captureIndices[0].getEnd(); + lineTokens.produce(stack, captureIndices[0].end); + anchorPosition = captureIndices[0].end; - String contentName = pushedRule.getContentName(lineText.string, captureIndices); - ScopeListElement contentNameScopesList = nameScopesList.push(grammar, contentName); + final String contentName = pushedRule.getContentName(lineText.string, captureIndices); + final ScopeListElement contentNameScopesList = nameScopesList.push(grammar, contentName); stack = stack.setContentNameScopesList(contentNameScopesList); if (pushedRule.whileHasBackReferences) { @@ -217,14 +236,15 @@ private void scanNext() { if (!hasAdvanced && beforePush.hasSameRuleAs(stack)) { // Grammar pushed the same rule without advancing - LOGGER.info("[3] - Grammar is in an endless loop - Grammar pushed the same rule without advancing"); - stack = stack.pop(); - lineTokens.produce(stack, lineLength); + LOGGER.log(INFO, + "[3] - Grammar is in an endless loop - Grammar pushed the same rule without advancing"); + stack = castNonNull(stack.pop()); + lineTokens.produce(stack, lineText.bytesCount); stop = true; return; } } else { - MatchRule matchingRule = (MatchRule) rule; + final MatchRule matchingRule = (MatchRule) rule; // if (IN_DEBUG_MODE) { // console.log(' matched ' + matchingRule.debugName + ' - ' + // matchingRule.debugMatchRegExp); @@ -232,34 +252,37 @@ private void scanNext() { handleCaptures(grammar, lineText, isFirstLine, stack, lineTokens, matchingRule.captures, captureIndices); - lineTokens.produce(stack, captureIndices[0].getEnd()); + lineTokens.produce(stack, captureIndices[0].end); // pop rule immediately since it is a MatchRule - stack = stack.pop(); + stack = castNonNull(stack.pop()); if (!hasAdvanced) { // Grammar is not advancing, nor is it pushing/popping - LOGGER.info("[4] - Grammar is in an endless loop - Grammar is not advancing, nor is it pushing/popping"); + LOGGER.log(INFO, + "[4] - Grammar is in an endless loop - Grammar is not advancing, nor is it pushing/popping"); stack = stack.safePop(); - lineTokens.produce(stack, lineLength); + lineTokens.produce(stack, lineText.bytesCount); stop = true; return; } } } - if (captureIndices != null && captureIndices.length > 0 && captureIndices[0].getEnd() > linePos) { + if (captureIndices.length > 0 && captureIndices[0].end > linePos) { // Advance stream - linePos = captureIndices[0].getEnd(); + linePos = captureIndices[0].end; isFirstLine = false; } } - private IMatchResult matchRule(Grammar grammar, OnigString lineText, boolean isFirstLine, final int linePos, - StackElement stack, int anchorPosition) { - Rule rule = stack.getRule(grammar); - final ICompiledRule ruleScanner = rule.compile(grammar, stack.endRule, isFirstLine, linePos == anchorPosition); - final IOnigNextMatchResult r = ruleScanner.scanner.findNextMatchSync(lineText, linePos); + @Nullable + private IMatchResult matchRule(final Grammar grammar, final OnigString lineText, final boolean isFirstLine, + final int linePos, final StackElement stack, final int anchorPosition) { + final Rule rule = stack.getRule(grammar); + final CompiledRule ruleScanner = rule.compileAG(grammar, stack.endRule, isFirstLine, linePos == anchorPosition); + + final OnigNextMatchResult r = ruleScanner.scanner.findNextMatchSync(lineText, linePos); if (r != null) { return new IMatchResult() { @@ -270,7 +293,7 @@ public int getMatchedRuleId() { } @Override - public IOnigCaptureIndex[] getCaptureIndices() { + public OnigCaptureIndex[] getCaptureIndices() { return r.getCaptureIndices(); } }; @@ -278,19 +301,22 @@ public IOnigCaptureIndex[] getCaptureIndices() { return null; } - private IMatchResult matchRuleOrInjections(Grammar grammar, OnigString lineText, boolean isFirstLine, - final int linePos, StackElement stack, int anchorPosition) { + @Nullable + private IMatchResult matchRuleOrInjections(final Grammar grammar, final OnigString lineText, + final boolean isFirstLine, + final int linePos, final StackElement stack, final int anchorPosition) { // Look for normal grammar rule - IMatchResult matchResult = matchRule(grammar, lineText, isFirstLine, linePos, stack, anchorPosition); + final IMatchResult matchResult = matchRule(grammar, lineText, isFirstLine, linePos, stack, anchorPosition); // Look for injected rules - List injections = grammar.getInjections(); - if (injections.size() == 0) { + final List injections = grammar.getInjections(); + if (injections.isEmpty()) { // No injections whatsoever => early return return matchResult; } - IMatchInjectionsResult injectionResult = matchInjections(injections, grammar, lineText, isFirstLine, linePos, + final IMatchInjectionsResult injectionResult = matchInjections(injections, grammar, lineText, isFirstLine, + linePos, stack, anchorPosition); if (injectionResult == null) { // No injections matched => early return @@ -303,8 +329,8 @@ private IMatchResult matchRuleOrInjections(Grammar grammar, OnigString lineText, } // Decide if `matchResult` or `injectionResult` should win - int matchResultScore = matchResult.getCaptureIndices()[0].getStart(); - int injectionResultScore = injectionResult.getCaptureIndices()[0].getStart(); + final int matchResultScore = matchResult.getCaptureIndices()[0].start; + final int injectionResultScore = injectionResult.getCaptureIndices()[0].start; if (injectionResultScore < matchResultScore || (injectionResult.isPriorityMatch() && injectionResultScore == matchResultScore)) { @@ -315,31 +341,37 @@ private IMatchResult matchRuleOrInjections(Grammar grammar, OnigString lineText, return matchResult; } - private IMatchInjectionsResult matchInjections(List injections, Grammar grammar, OnigString lineText, - boolean isFirstLine, int linePos, StackElement stack, int anchorPosition) { + @Nullable + private IMatchInjectionsResult matchInjections(final List injections, final Grammar grammar, + final OnigString lineText, + final boolean isFirstLine, final int linePos, final StackElement stack, final int anchorPosition) { // The lower the better int bestMatchRating = Integer.MAX_VALUE; - IOnigCaptureIndex[] bestMatchCaptureIndices = null; + OnigCaptureIndex[] bestMatchCaptureIndices = null; int bestMatchRuleId = -1; int bestMatchResultPriority = 0; - List scopes = stack.contentNameScopesList.generateScopes(); + final List scopes = stack.contentNameScopesList.generateScopes(); - for (Injection injection : injections) { - if (!injection.match(scopes)) { + for (final Injection injection : injections) { + if (!injection.matches(scopes)) { // injection selector doesn't match stack continue; } - ICompiledRule ruleScanner = grammar.getRule(injection.ruleId).compile(grammar, null, isFirstLine, + final CompiledRule ruleScanner = grammar.getRule(injection.ruleId).compileAG(grammar, null, isFirstLine, linePos == anchorPosition); - IOnigNextMatchResult matchResult = ruleScanner.scanner.findNextMatchSync(lineText, linePos); + final OnigNextMatchResult matchResult = ruleScanner.scanner.findNextMatchSync(lineText, linePos); if (matchResult == null) { continue; } - int matchRating = matchResult.getCaptureIndices()[0].getStart(); + if (LOGGER.isLoggable(Level.TRACE)) { + LOGGER.log(Level.TRACE, " matched injection: " + injection.debugSelector); + LOGGER.log(Level.TRACE, debugCompiledRuleToString(ruleScanner)); + } + final int matchRating = matchResult.getCaptureIndices()[0].start; if (matchRating > bestMatchRating) { // Injections are sorted by priority, so the previous injection had a better or @@ -360,7 +392,7 @@ private IMatchInjectionsResult matchInjections(List injections, Gramm if (bestMatchCaptureIndices != null) { final int matchedRuleId = bestMatchRuleId; - final IOnigCaptureIndex[] matchCaptureIndices = bestMatchCaptureIndices; + final OnigCaptureIndex[] matchCaptureIndices = bestMatchCaptureIndices; final boolean matchResultPriority = bestMatchResultPriority == -1; return new IMatchInjectionsResult() { @@ -370,7 +402,7 @@ public int getMatchedRuleId() { } @Override - public IOnigCaptureIndex[] getCaptureIndices() { + public OnigCaptureIndex[] getCaptureIndices() { return matchCaptureIndices; } @@ -384,19 +416,21 @@ public boolean isPriorityMatch() { return null; } - private void handleCaptures(Grammar grammar, OnigString lineText, boolean isFirstLine, StackElement stack, - LineTokens lineTokens, List captures, IOnigCaptureIndex[] captureIndices) { + private void handleCaptures(final Grammar grammar, final OnigString lineText, final boolean isFirstLine, + final StackElement stack, + final LineTokens lineTokens, final List<@Nullable CaptureRule> captures, + final OnigCaptureIndex[] captureIndices) { if (captures.isEmpty()) { return; } - int len = Math.min(captures.size(), captureIndices.length); - List localStack = new ArrayList(); - int maxEnd = captureIndices[0].getEnd(); - IOnigCaptureIndex captureIndex; + final int len = Math.min(captures.size(), captureIndices.length); + final var localStack = new ArrayDeque(); + final int maxEnd = captureIndices[0].end; + OnigCaptureIndex captureIndex; for (int i = 0; i < len; i++) { - CaptureRule captureRule = captures.get(i); + final CaptureRule captureRule = captures.get(i); if (captureRule == null) { // Not interested continue; @@ -409,58 +443,57 @@ private void handleCaptures(Grammar grammar, OnigString lineText, boolean isFirs continue; } - if (captureIndex.getStart() > maxEnd) { + if (captureIndex.start > maxEnd) { // Capture going beyond consumed string break; } // pop captures while needed - while (!localStack.isEmpty() && localStack.get(localStack.size() - 1).getEndPos() <= captureIndex.getStart()) { + while (!localStack.isEmpty() && localStack.getLast().endPos <= captureIndex.start) { // pop! - lineTokens.produceFromScopes(localStack.get(localStack.size() - 1).getScopes(), - localStack.get(localStack.size() - 1).getEndPos()); - localStack.remove(localStack.size() - 1); + final var lastElem = localStack.removeLast(); + lineTokens.produceFromScopes(lastElem.scopes, lastElem.endPos); } if (!localStack.isEmpty()) { - lineTokens.produceFromScopes(localStack.get(localStack.size() - 1).getScopes(), - captureIndex.getStart()); + lineTokens.produceFromScopes(localStack.getLast().scopes, captureIndex.start); } else { - lineTokens.produce(stack, captureIndex.getStart()); + lineTokens.produce(stack, captureIndex.start); } - if (captureRule.retokenizeCapturedWithRuleId != null) { + final var retokenizeCapturedWithRuleId = captureRule.retokenizeCapturedWithRuleId; + if (retokenizeCapturedWithRuleId != null) { // the capture requires additional matching - String scopeName = captureRule.getName(lineText.string, captureIndices); - ScopeListElement nameScopesList = stack.contentNameScopesList.push(grammar, scopeName); - String contentName = captureRule.getContentName(lineText.string, captureIndices); - ScopeListElement contentNameScopesList = nameScopesList.push(grammar, contentName); + final String scopeName = captureRule.getName(lineText.string, captureIndices); + final ScopeListElement nameScopesList = stack.contentNameScopesList.push(grammar, scopeName); + final String contentName = captureRule.getContentName(lineText.string, captureIndices); + final ScopeListElement contentNameScopesList = nameScopesList.push(grammar, contentName); // the capture requires additional matching - StackElement stackClone = stack.push(captureRule.retokenizeCapturedWithRuleId, captureIndex.getStart(), + final StackElement stackClone = stack.push(retokenizeCapturedWithRuleId, captureIndex.start, -1, false, null, nameScopesList, contentNameScopesList); - tokenizeString(grammar, - GrammarHelper.createOnigString(lineText.string.substring(0, captureIndex.getEnd())), - (isFirstLine && captureIndex.getStart() == 0), captureIndex.getStart(), stackClone, lineTokens); + final var onigSubStr = OnigString.of(lineText.string.substring(0, captureIndex.end)); + tokenizeString(grammar, onigSubStr, (isFirstLine && captureIndex.start == 0), + captureIndex.start, stackClone, lineTokens, false); continue; } // push - String captureRuleScopeName = captureRule.getName(lineText.string, captureIndices); + final String captureRuleScopeName = captureRule.getName(lineText.string, captureIndices); if (captureRuleScopeName != null) { // push - ScopeListElement base = localStack.isEmpty() ? stack.contentNameScopesList : - localStack.get(localStack.size() - 1).getScopes(); - ScopeListElement captureRuleScopesList = base.push(grammar, captureRuleScopeName); - localStack.add(new LocalStackElement(captureRuleScopesList, captureIndex.getEnd())); + final ScopeListElement base = localStack.isEmpty() + ? stack.contentNameScopesList + : localStack.getLast().scopes; + final ScopeListElement captureRuleScopesList = base.push(grammar, captureRuleScopeName); + localStack.add(new LocalStackElement(captureRuleScopesList, captureIndex.end)); } } while (!localStack.isEmpty()) { // pop! - lineTokens.produceFromScopes(localStack.get(localStack.size() - 1).getScopes(), - localStack.get(localStack.size() - 1).getEndPos()); - localStack.remove(localStack.size() - 1); + final var lastElem = localStack.removeLast(); + lineTokens.produceFromScopes(lastElem.scopes, lastElem.endPos); } } @@ -469,46 +502,47 @@ private void handleCaptures(Grammar grammar, OnigString lineText, boolean isFirs * order. If any fails, cut off the entire stack above the failed while * condition. While conditions may also advance the linePosition. */ - private WhileCheckResult checkWhileConditions(Grammar grammar, OnigString lineText, boolean isFirstLine, - int linePos, StackElement stack, LineTokens lineTokens) { - int currentanchorPosition = -1; - List whileRules = new ArrayList<>(); + private WhileCheckResult checkWhileConditions(final Grammar grammar, final OnigString lineText, boolean isFirstLine, + int linePos, StackElement stack, final LineTokens lineTokens) { + int currentanchorPosition = stack.beginRuleCapturedEOL ? 0 : -1; + final List whileRules = new ArrayList<>(); for (StackElement node = stack; node != null; node = node.pop()) { - Rule nodeRule = node.getRule(grammar); + final Rule nodeRule = node.getRule(grammar); if (nodeRule instanceof BeginWhileRule) { whileRules.add(new WhileStack(node, (BeginWhileRule) nodeRule)); } } + for (int i = whileRules.size() - 1; i >= 0; i--) { - WhileStack whileRule = whileRules.get(i); - ICompiledRule ruleScanner = whileRule.rule.compileWhile(grammar, whileRule.stack.endRule, isFirstLine, + final var whileRule = whileRules.get(i); + final var ruleScanner = whileRule.rule.compileWhileAG(whileRule.stack.endRule, isFirstLine, currentanchorPosition == linePos); - IOnigNextMatchResult r = ruleScanner.scanner.findNextMatchSync(lineText, linePos); - // if (IN_DEBUG_MODE) { - // console.log(' scanning for while rule'); - // console.log(debugCompiledRuleToString(ruleScanner)); - // } + final var r = ruleScanner.scanner.findNextMatchSync(lineText, linePos); + if (LOGGER.isLoggable(TRACE)) { + LOGGER.log(TRACE, " scanning for while rule"); + LOGGER.log(TRACE, debugCompiledRuleToString(ruleScanner)); + } if (r != null) { - Integer matchedRuleId = ruleScanner.rules[r.getIndex()]; + final int matchedRuleId = ruleScanner.rules[r.getIndex()]; if (matchedRuleId != -2) { // we shouldn't end up here - stack = whileRule.stack.pop(); + stack = castNonNull(whileRule.stack.pop()); break; } - if (r.getCaptureIndices() != null && r.getCaptureIndices().length > 0) { - lineTokens.produce(whileRule.stack, r.getCaptureIndices()[0].getStart()); + if (r.getCaptureIndices().length > 0) { + lineTokens.produce(whileRule.stack, r.getCaptureIndices()[0].start); handleCaptures(grammar, lineText, isFirstLine, whileRule.stack, lineTokens, whileRule.rule.whileCaptures, r.getCaptureIndices()); - lineTokens.produce(whileRule.stack, r.getCaptureIndices()[0].getEnd()); - currentanchorPosition = r.getCaptureIndices()[0].getEnd(); - if (r.getCaptureIndices()[0].getEnd() > linePos) { - linePos = r.getCaptureIndices()[0].getEnd(); + lineTokens.produce(whileRule.stack, r.getCaptureIndices()[0].end); + currentanchorPosition = r.getCaptureIndices()[0].end; + if (r.getCaptureIndices()[0].end > linePos) { + linePos = r.getCaptureIndices()[0].end; isFirstLine = false; } } } else { - stack = whileRule.stack.pop(); + stack = castNonNull(whileRule.stack.pop()); break; } } @@ -516,8 +550,17 @@ private WhileCheckResult checkWhileConditions(Grammar grammar, OnigString lineTe return new WhileCheckResult(stack, linePos, currentanchorPosition, isFirstLine); } - public static StackElement tokenizeString(Grammar grammar, OnigString lineText, boolean isFirstLine, int linePos, - StackElement stack, LineTokens lineTokens) { - return new LineTokenizer(grammar, lineText, isFirstLine, linePos, stack, lineTokens).scan(); + static StackElement tokenizeString(final Grammar grammar, final OnigString lineText, final boolean isFirstLine, + final int linePos, final StackElement stack, final LineTokens lineTokens, + final boolean checkWhileConditions) { + return new LineTokenizer(grammar, lineText, isFirstLine, linePos, stack, lineTokens).scan(checkWhileConditions); + } + + static String debugCompiledRuleToString(final CompiledRule ruleScanner) { + final var r = new ArrayList(); + for (int i = 0, l = ruleScanner.rules.length; i < l; i++) { + r.add(" - " + ruleScanner.rules[i] + ": " + ruleScanner.debugRegExps.get(i)); + } + return String.join(System.lineSeparator(), r); } } diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/LineTokens.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/LineTokens.java index 7c609b7e8..e40704cf3 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/LineTokens.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/LineTokens.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2022 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,70 +11,139 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.grammar; - + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.grammar; + +import static java.lang.System.Logger.Level.*; +import static org.eclipse.tm4e.core.internal.utils.MoreCollections.*; +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import java.lang.System.Logger; +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Collections; +import java.util.Deque; import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tm4e.core.grammar.IToken; -import org.eclipse.tm4e.core.grammar.StackElement; - -class LineTokens { +import org.eclipse.tm4e.core.internal.theme.FontStyle; - private static final Logger LOGGER = Logger.getLogger(LineTokens.class.getName()); +final class LineTokens { - private final String lineText; + private static final Logger LOGGER = System.getLogger(LineTokens.class.getName()); + + private static final Deque EMPTY_DEQUE = new ArrayDeque<>(0); /** - * used only if `_emitBinaryTokens` is false. - */ - private final List tokens; + * defined only if `LOGGER.isLoggable(TRACE)`. + */ + @Nullable + private final String lineText; + /** + * used only if `emitBinaryTokens` is false. + */ + private final Deque tokens; - private boolean emitBinaryTokens; + private final boolean emitBinaryTokens; /** - * used only if `_emitBinaryTokens` is true. + * used only if `emitBinaryTokens` is true. */ private final List binaryTokens; - - private int lastTokenEndIndex; - - LineTokens(boolean emitBinaryTokens, String lineText) { + + private int lastTokenEndIndex = 0; + + private final List tokenTypeOverrides; + + @Nullable + private final BalancedBracketSelectors balancedBracketSelectors; + + LineTokens(final boolean emitBinaryTokens, final String lineText, final List tokenTypeOverrides, + @Nullable final BalancedBracketSelectors balancedBracketSelectors) { this.emitBinaryTokens = emitBinaryTokens; - this.lineText = LOGGER.isLoggable(Level.FINEST) ? lineText : null; // store line only if it's logged + this.lineText = LOGGER.isLoggable(TRACE) ? lineText : null; // store line only if it's logged if (this.emitBinaryTokens) { - this.tokens = null; + this.tokens = EMPTY_DEQUE; this.binaryTokens = new ArrayList<>(); } else { - this.tokens = new ArrayList<>(); - this.binaryTokens = null; - } - this.lastTokenEndIndex = 0; - } - - public void produce(StackElement stack, int endIndex) { + this.tokens = new ArrayDeque<>(); + this.binaryTokens = Collections.emptyList(); + } + this.tokenTypeOverrides = tokenTypeOverrides; + this.balancedBracketSelectors = balancedBracketSelectors; + } + + void produce(final StackElement stack, final int endIndex) { this.produceFromScopes(stack.contentNameScopesList, endIndex); - } + } - public void produceFromScopes(ScopeListElement scopesList, int endIndex) { + void produceFromScopes(final ScopeListElement scopesList, final int endIndex) { if (this.lastTokenEndIndex >= endIndex) { return; } if (this.emitBinaryTokens) { int metadata = scopesList.metadata; - if (!this.binaryTokens.isEmpty() && this.binaryTokens.get(this.binaryTokens.size() - 1) == metadata) { + var containsBalancedBrackets = false; + final var balancedBracketSelectors = this.balancedBracketSelectors; + if (balancedBracketSelectors != null && balancedBracketSelectors.matchesAlways()) { + containsBalancedBrackets = true; + } + + if (!tokenTypeOverrides.isEmpty() || (balancedBracketSelectors != null + && !balancedBracketSelectors.matchesAlways() && !balancedBracketSelectors.matchesNever())) { + // Only generate scope array when required to improve performance + final var scopes = scopesList.generateScopes(); + for (final var tokenType : tokenTypeOverrides) { + if (tokenType.getMatcher().matches(scopes)) { + metadata = StackElementMetadata.set( + metadata, + 0, + tokenType.getType(), // toOptionalTokenType(tokenType.type), + null, + FontStyle.NotSet, + 0, + 0); + } + } + if (balancedBracketSelectors != null) { + containsBalancedBrackets = balancedBracketSelectors.match(scopes); + } + } + + if (containsBalancedBrackets) { + metadata = StackElementMetadata.set( + metadata, + 0, + OptionalStandardTokenType.NotSet, + containsBalancedBrackets, + FontStyle.NotSet, + 0, + 0); + } + + if (!this.binaryTokens.isEmpty() && getLastElement(this.binaryTokens) == metadata) { // no need to push a token with the same metadata this.lastTokenEndIndex = endIndex; return; } + if (LOGGER.isLoggable(TRACE)) { + final List scopes = scopesList.generateScopes(); + LOGGER.log(TRACE, " token: |" + + castNonNull(this.lineText) + .substring(this.lastTokenEndIndex >= 0 ? this.lastTokenEndIndex : 0, endIndex) + .replace("\n", "\\n") + + '|'); + for (final String scope : scopes) { + LOGGER.log(TRACE, " * " + scope); + } + } + this.binaryTokens.add(this.lastTokenEndIndex); this.binaryTokens.add(metadata); @@ -82,52 +151,55 @@ public void produceFromScopes(ScopeListElement scopesList, int endIndex) { return; } - List scopes = scopesList.generateScopes(); + final List scopes = scopesList.generateScopes(); - if (this.lineText != null) { - LOGGER.info(" token: |" + this.lineText.substring(this.lastTokenEndIndex, endIndex).replaceAll("\n", "\\n") + '|'); - for (String scope : scopes) { - LOGGER.info(" * " + scope); + if (LOGGER.isLoggable(TRACE)) { + LOGGER.log(TRACE, " token: |" + + castNonNull(this.lineText) + .substring(this.lastTokenEndIndex >= 0 ? this.lastTokenEndIndex : 0, endIndex) + .replace("\n", "\\n") + + '|'); + for (final String scope : scopes) { + LOGGER.log(TRACE, " * " + scope); } } - this.tokens.add(new Token(this.lastTokenEndIndex, endIndex, scopes)); + + this.tokens.add(new Token( + this.lastTokenEndIndex >= 0 ? this.lastTokenEndIndex : 0, + endIndex, + scopes)); this.lastTokenEndIndex = endIndex; } - - public IToken[] getResult(StackElement stack, int lineLength) { - if (!this.tokens.isEmpty() && this.tokens.get(this.tokens.size() - 1).getStartIndex() == lineLength - 1) { - // pop produced token for newline - this.tokens.remove(this.tokens.size() - 1); - } - - if (this.tokens.isEmpty()) { - this.lastTokenEndIndex = -1; - this.produce(stack, lineLength); - this.tokens.get(this.tokens.size() - 1).setStartIndex(0); - } - - return this.tokens.toArray(new IToken[0]); - } - public int[] getBinaryResult(StackElement stack, int lineLength) { - if (!this.binaryTokens.isEmpty() && this.binaryTokens.get(this.binaryTokens.size() - 2) == lineLength - 1) { + IToken[] getResult(final StackElement stack, final int lineLength) { + if (!this.tokens.isEmpty() && this.tokens.getLast().getStartIndex() == lineLength - 1) { // pop produced token for newline - this.binaryTokens.remove(this.binaryTokens.size() - 1); - this.binaryTokens.remove(this.binaryTokens.size() - 1); + this.tokens.removeLast(); } - if (this.binaryTokens.isEmpty()) { + if (this.tokens.isEmpty()) { this.lastTokenEndIndex = -1; this.produce(stack, lineLength); - this.binaryTokens.set(this.binaryTokens.size() - 2, 0); + this.tokens.getLast().setStartIndex(0); } - int[] result = new int[this.binaryTokens.size()]; - for (int i = 0, len = this.binaryTokens.size(); i < len; i++) { - result[i] = this.binaryTokens.get(i); + return this.tokens.toArray(IToken[]::new); + } + + int[] getBinaryResult(final StackElement stack, final int lineLength) { + if (!this.binaryTokens.isEmpty() && this.binaryTokens.get(binaryTokens.size() - 2) == lineLength - 1) { + // pop produced token for newline + removeLastElement(this.binaryTokens); + removeLastElement(this.binaryTokens); } - return result; - } -} + if (this.binaryTokens.isEmpty()) { + this.lastTokenEndIndex = -1; + this.produce(stack, lineLength); + this.binaryTokens.set(binaryTokens.size() - 2, 0); + } + + return binaryTokens.stream().mapToInt(Integer::intValue).toArray(); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/LocalStackElement.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/LocalStackElement.java index 4d5c7388b..7f67b97f0 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/LocalStackElement.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/LocalStackElement.java @@ -13,25 +13,16 @@ * Contributors: * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.grammar; - -class LocalStackElement { - - private final ScopeListElement scopes; - private final int endPos; - - public LocalStackElement(ScopeListElement scopes, int endPos) { - this.scopes = scopes; - this.endPos = endPos; - } - - public ScopeListElement getScopes() { - return scopes; - } - - public int getEndPos() { - return endPos; - } - -} + */ +package org.eclipse.tm4e.core.internal.grammar; + +final class LocalStackElement { + + final ScopeListElement scopes; + final int endPos; + + LocalStackElement(final ScopeListElement scopes, final int endPos) { + this.scopes = scopes; + this.endPos = endPos; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/MetadataConsts.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/MetadataConsts.java index b1e567587..1a93039c5 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/MetadataConsts.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/MetadataConsts.java @@ -9,45 +9,52 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.core.internal.grammar; - -/** - * Helpers to manage the "collapsed" metadata of an entire StackElement stack. - * The following assumptions have been made: - * - languageId < 256 => needs 8 bits - * - unique color count < 512 => needs 9 bits - * - * The binary format is: - * - ------------------------------------------- - * 3322 2222 2222 1111 1111 1100 0000 0000 - * 1098 7654 3210 9876 5432 1098 7654 3210 - * - ------------------------------------------- - * xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx - * bbbb bbbb bfff ffff ffFF FTTT LLLL LLLL - * - ------------------------------------------- - * - L = LanguageId (8 bits) - * - T = StandardTokenType (3 bits) - * - F = FontStyle (3 bits) - * - f = foreground color (9 bits) - * - b = background color (9 bits) - */ -public class MetadataConsts { +package org.eclipse.tm4e.core.internal.grammar; + +/** + * Helpers to manage the "collapsed" metadata of an entire StackElement stack. + * The following assumptions have been made: + * - languageId < 256 => needs 8 bits + * - unique color count < 512 => needs 9 bits + * + * The binary format is: + * - ------------------------------------------- + * 3322 2222 2222 1111 1111 1100 0000 0000 + * 1098 7654 3210 9876 5432 1098 7654 3210 + * - ------------------------------------------- + * xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx + * bbbb bbbb ffff ffff fFFF FBTT LLLL LLLL + * - ------------------------------------------- + * - L = LanguageId (8 bits) + * - T = StandardTokenType (2 bits) + * - B = Balanced bracket (1 bit) + * - F = FontStyle (4 bits) + * - f = foreground color (9 bits) + * - b = background color (9 bits) + * + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/metadata.ts + */ +final class MetadataConsts { /** * content should be accessed statically */ private MetadataConsts() { - } - - public static final int LANGUAGEID_MASK = 0b00000000000000000000000011111111; - public static final int TOKEN_TYPE_MASK = 0b00000000000000000000011100000000; - public static final int FONT_STYLE_MASK = 0b00000000000000000011100000000000; - public static final int FOREGROUND_MASK = 0b00000000011111111100000000000000; - public static final int BACKGROUND_MASK = 0b11111111100000000000000000000000; - - public static final int LANGUAGEID_OFFSET = 0; - public static final int TOKEN_TYPE_OFFSET = 8; - public static final int FONT_STYLE_OFFSET = 11; - public static final int FOREGROUND_OFFSET = 14; - public static final int BACKGROUND_OFFSET = 23; -} + } + + static final int LANGUAGEID_MASK = 0b00000000000000000000000011111111; + static final int TOKEN_TYPE_MASK = 0b00000000000000000000001100000000; + static final int BALANCED_BRACKETS_MASK = 0b00000000000000000000010000000000; + static final int FONT_STYLE_MASK = 0b00000000000000000111100000000000; + static final int FOREGROUND_MASK = 0b00000000111111111000000000000000; + static final int BACKGROUND_MASK = 0b11111111000000000000000000000000; + + static final int LANGUAGEID_OFFSET = 0; + static final int TOKEN_TYPE_OFFSET = 8; + static final int BALANCED_BRACKETS_OFFSET = 10; + static final int FONT_STYLE_OFFSET = 11; + static final int FOREGROUND_OFFSET = 15; + static final int BACKGROUND_OFFSET = 24; +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/OptionalStandardTokenType.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/OptionalStandardTokenType.java new file mode 100644 index 000000000..b1139aefc --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/OptionalStandardTokenType.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2022 Sebastian Thomschke and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Initial code from https://github.com/Microsoft/vscode-textmate/ + * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. + * Initial license: MIT + * + * Contributors: + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Sebastian Thomschke - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.grammar; + +/** + * Standard TextMate token type. + */ +final class OptionalStandardTokenType { + + /** + * Content should be accessed statically + */ + private OptionalStandardTokenType() { + } + + static final int Other = StandardTokenType.Other; + static final int Comment = StandardTokenType.Comment; + static final int String = StandardTokenType.String; + static final int RegEx = StandardTokenType.RegEx; + + /** + * Indicates that no token type is set. + */ + static final int NotSet = 8; +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/RawCaptures.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/RawCaptures.java new file mode 100644 index 000000000..2d86b8bc8 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/RawCaptures.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2022 Sebastian Thomschke and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.tm4e.core.internal.grammar; + +import java.util.HashMap; + +import org.eclipse.tm4e.core.internal.parser.PropertySettable; +import org.eclipse.tm4e.core.internal.types.IRawCaptures; +import org.eclipse.tm4e.core.internal.types.IRawRule; +import org.eclipse.tm4e.core.internal.utils.DeepCloneable; + +public class RawCaptures extends HashMap implements IRawCaptures, DeepCloneable, PropertySettable { + + private static final long serialVersionUID = 1L; + + @Override + public RawCaptures deepClone() { + final var clone = new RawCaptures(); + for (final var entry : entrySet()) { + clone.put(entry.getKey(), DeepCloneable.deepClone(entry.getValue())); + } + return clone; + } + + @Override + public IRawRule getCapture(final String captureId) { + return get(captureId); + } + + @Override + public Iterable getCaptureIds() { + return keySet(); + } + + @Override + public void setProperty(final String name, final IRawRule value) { + put(name, value); + } +} \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/RawGrammar.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/RawGrammar.java new file mode 100644 index 000000000..876e5f225 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/RawGrammar.java @@ -0,0 +1,179 @@ +/** + * Copyright (c) 2015-2019 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + * Pierre-Yves B. - Issue #221 NullPointerException when retrieving fileTypes + */ +package org.eclipse.tm4e.core.internal.grammar; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Objects; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.parser.PropertySettable; +import org.eclipse.tm4e.core.internal.types.IRawGrammar; +import org.eclipse.tm4e.core.internal.types.IRawRepository; +import org.eclipse.tm4e.core.internal.types.IRawRule; +import org.eclipse.tm4e.core.internal.utils.DeepCloneable; + +public class RawGrammar extends HashMap + implements IRawGrammar, DeepCloneable, PropertySettable { + + private static final String FILE_TYPES = "fileTypes"; + private static final String FIRST_LINE_MATCH = "firstLineMatch"; + private static final String INJECTIONS = "injections"; + private static final String INJECTION_SELECTOR = "injectionSelector"; + private static final String NAME = "name"; + private static final String PATTERNS = "patterns"; + private static final String SCOPE_NAME = "scopeName"; + + private static final long serialVersionUID = 1L; + + @Nullable + private transient List fileTypes; + + @Override + public RawGrammar deepClone() { + final var clone = new RawGrammar(); + for (final var entry : entrySet()) { + clone.put(entry.getKey(), DeepCloneable.deepClone(entry.getValue())); + } + return clone; + } + + @Override + public Collection getFileTypes() { + List result = fileTypes; + if (result == null) { + result = new ArrayList<>(); + final Collection unparsedFileTypes = (Collection) get(FILE_TYPES); + if (unparsedFileTypes != null) { + for (final Object o : unparsedFileTypes) { + String str = Objects.toString(o); + // #202 + if (str.startsWith(".")) { + str = str.substring(1); + } + result.add(str); + } + } + fileTypes = result; + } + return result; + } + + @Override + @Nullable + public String getFirstLineMatch() { + return (String) get(FIRST_LINE_MATCH); + } + + @Nullable + @Override + @SuppressWarnings("unchecked") + public Map getInjections() { + return (Map) get(INJECTIONS); + } + + @Nullable + @Override + public String getInjectionSelector() { + return (String) get(INJECTION_SELECTOR); + } + + @Nullable + @Override + public String getName() { + return (String) get(NAME); + } + + @SuppressWarnings("unchecked") + @Override + public @Nullable Collection getPatterns() { + return (Collection) get(PATTERNS); + } + + @Override + public boolean isRepositorySet() { + return containsKey(RawRule.REPOSITORY); + } + + @Override + public IRawRepository getRepository() { + return (IRawRepository) getSafe(RawRule.REPOSITORY); + } + + private Object getSafe(@Nullable final Object key) { + @SuppressWarnings("unlikely-arg-type") + final var obj = get(key); + if (obj == null) { + throw new NoSuchElementException("Key '" + key + "' does not exit found"); + } + return obj; + } + + @Override + public String getScopeName() { + return (String) getSafe(SCOPE_NAME); + } + + @Nullable + @Override + public Object put(final String key, @Nullable final Object value) { + if (FILE_TYPES.equals(key)) + fileTypes = null; + + return super.put(key, value); + } + + @Override + @SuppressWarnings("unlikely-arg-type") + public void putAll(@Nullable final Map m) { + if (m != null && m.containsKey(FILE_TYPES)) + fileTypes = null; + super.putAll(m); + } + + @Override + public void setProperty(final String name, final Object value) { + put(name, value); + } + + @Override + public void setRepository(final IRawRepository repository) { + super.put(RawRule.REPOSITORY, repository); + } + + @Override + public IRawRule toRawRule() { + return new RawRule() { + private static final long serialVersionUID = 1L; + + @Override + public @Nullable String getName() { + return RawGrammar.this.getName(); + } + + @Override + public @Nullable Collection getPatterns() { + return RawGrammar.this.getPatterns(); + } + + @Override + public @Nullable IRawRepository getRepository() { + return isRepositorySet() ? RawGrammar.this.getRepository() : null; + } + }; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/RawRepository.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/RawRepository.java new file mode 100644 index 000000000..f71279489 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/RawRepository.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2015-2019 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.grammar; + +import java.util.HashMap; +import java.util.NoSuchElementException; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.parser.PropertySettable; +import org.eclipse.tm4e.core.internal.types.IRawRepository; +import org.eclipse.tm4e.core.internal.types.IRawRule; +import org.eclipse.tm4e.core.internal.utils.DeepCloneable; + +public class RawRepository extends HashMap + implements IRawRepository, DeepCloneable, PropertySettable { + + private static final long serialVersionUID = 1L; + + public static final String DOLLAR_BASE = "$base"; + public static final String DOLLAR_SELF = "$self"; + + @Override + public RawRepository deepClone() { + final var clone = new RawRepository(); + for (final var entry : entrySet()) { + clone.put(entry.getKey(), DeepCloneable.deepClone(entry.getValue())); + } + return clone; + } + + @SuppressWarnings({ "null", "unused" }) + private IRawRule getSafe(final String key) { + final IRawRule obj = get(key); + if (obj == null) { + throw new NoSuchElementException("Key '" + key + "' does not exit found"); + } + return obj; + } + + @Override + @Nullable + public IRawRule getRule(final String name) { + return get(name); + } + + @Override + public IRawRule getBase() { + return getSafe(DOLLAR_BASE); + } + + @Override + public void setBase(final IRawRule base) { + super.put(DOLLAR_BASE, base); + } + + @Override + public IRawRule getSelf() { + return getSafe(DOLLAR_SELF); + } + + @Override + public void setSelf(final IRawRule self) { + super.put(DOLLAR_SELF, self); + } + + @Override + public void putEntries(final PropertySettable target) { + for (final var entry : entrySet()) { + target.setProperty(entry.getKey(), entry.getValue()); + } + } + + @Override + public void setProperty(final String name, final IRawRule value) { + put(name, value); + } +} \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/RawRule.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/RawRule.java new file mode 100644 index 000000000..e7047cbe5 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/RawRule.java @@ -0,0 +1,193 @@ +/** + * Copyright (c) 2015-2019 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.grammar; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.parser.PropertySettable; +import org.eclipse.tm4e.core.internal.types.IRawCaptures; +import org.eclipse.tm4e.core.internal.types.IRawRepository; +import org.eclipse.tm4e.core.internal.types.IRawRule; +import org.eclipse.tm4e.core.internal.utils.DeepCloneable; + +public class RawRule extends HashMap + implements IRawRule, DeepCloneable, PropertySettable { + + private static final String APPLY_END_PATTERN_LAST = "applyEndPatternLast"; + private static final String BEGIN = "begin"; + public static final String BEGIN_CAPTURES = "beginCaptures"; + public static final String CAPTURES = "captures"; + private static final String CONTENT_NAME = "contentName"; + private static final String END = "end"; + public static final String END_CAPTURES = "endCaptures"; + private static final String ID = "id"; + private static final String INCLUDE = "include"; + private static final String MATCH = "match"; + private static final String NAME = "name"; + private static final String PATTERNS = "patterns"; + public static final String REPOSITORY = "repository"; + private static final String WHILE = "while"; + public static final String WHILE_CAPTURES = "whileCaptures"; + + private static final long serialVersionUID = 1L; + + @Override + public RawRule deepClone() { + final var clone = new RawRule(); + for (final var entry : entrySet()) { + clone.put(entry.getKey(), DeepCloneable.deepClone(entry.getValue())); + } + return clone; + } + + @Nullable + @Override + public Integer getId() { + return (Integer) get(ID); + } + + @Override + public void setId(final Integer id) { + super.put(ID, id); + } + + @Nullable + @Override + public String getName() { + return (String) get(NAME); + } + + public void setName(final String name) { + super.put(NAME, name); + } + + @Nullable + @Override + public String getContentName() { + return (String) get(CONTENT_NAME); + } + + @Nullable + @Override + public String getMatch() { + return (String) get(MATCH); + } + + @Nullable + @Override + public IRawCaptures getCaptures() { + updateCaptures(CAPTURES); + return (IRawCaptures) get(CAPTURES); + } + + private void updateCaptures(final String name) { + final Object captures = get(name); + if (captures instanceof List) { + final RawRule rawCaptures = new RawRule(); + int i = 0; + for (final Object capture : (List) captures) { + i++; + rawCaptures.put(Integer.toString(i), capture); + } + super.put(name, rawCaptures); + } + } + + @Nullable + @Override + public String getBegin() { + return (String) get(BEGIN); + } + + @Nullable + @Override + public String getWhile() { + return (String) get(WHILE); + } + + @Nullable + @Override + public String getInclude() { + return (String) get(INCLUDE); + } + + public void setInclude(@Nullable final String include) { + super.put(INCLUDE, include); + } + + @Nullable + @Override + public IRawCaptures getBeginCaptures() { + updateCaptures(BEGIN_CAPTURES); + return (IRawCaptures) get(BEGIN_CAPTURES); + } + + @Nullable + @Override + public String getEnd() { + return (String) get(END); + } + + @Nullable + @Override + public IRawCaptures getEndCaptures() { + updateCaptures(END_CAPTURES); + return (IRawCaptures) get(END_CAPTURES); + } + + @Nullable + @Override + public IRawCaptures getWhileCaptures() { + updateCaptures(WHILE_CAPTURES); + return (IRawCaptures) get(WHILE_CAPTURES); + } + + @Nullable + @Override + @SuppressWarnings("unchecked") + public Collection getPatterns() { + return (Collection) get(PATTERNS); + } + + public void setPatterns(final @Nullable Collection patterns) { + super.put(PATTERNS, patterns); + } + + @Nullable + @Override + public IRawRepository getRepository() { + return (IRawRepository) get(REPOSITORY); + } + + @Override + public boolean isApplyEndPatternLast() { + final Object applyEndPatternLast = get(APPLY_END_PATTERN_LAST); + if (applyEndPatternLast == null) { + return false; + } + if (applyEndPatternLast instanceof Boolean) { + return (Boolean) applyEndPatternLast; + } + if (applyEndPatternLast instanceof Integer) { + return ((Integer) applyEndPatternLast) == 1; + } + return false; + } + + @Override + public void setProperty(final String name, final Object value) { + put(name, value); + } +} \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/ScopeDependencyProcessor.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/ScopeDependencyProcessor.java new file mode 100644 index 000000000..7b6145534 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/ScopeDependencyProcessor.java @@ -0,0 +1,255 @@ +/** + * Copyright (c) 2022 Sebastian Thomschke and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Initial code from https://github.com/Microsoft/vscode-textmate/ + * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. + * Initial license: MIT + * + * Contributors: + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Sebastian Thomschke - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.grammar; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.TMException; +import org.eclipse.tm4e.core.internal.registry.IGrammarRepository; +import org.eclipse.tm4e.core.internal.types.IRawGrammar; +import org.eclipse.tm4e.core.internal.types.IRawRepository; +import org.eclipse.tm4e.core.internal.types.IRawRule; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/grammar.ts + */ +class ScopeDependencyProcessor { + + private abstract static class ScopeDependency { + final String scopeName; + + ScopeDependency(final String scopeName) { + this.scopeName = scopeName; + } + } + + private static final class FullScopeDependency extends ScopeDependency { + FullScopeDependency(final String scopeName) { + super(scopeName); + } + } + + private static final class PartialScopeDependency extends ScopeDependency { + final String include; + + PartialScopeDependency(final String scopeName, final String include) { + super(scopeName); + this.include = include; + } + + String toKey() { + return this.scopeName + '#' + this.include; + } + } + + private static class ScopeDependencyCollector { + + final List full = new ArrayList<>(); + final List partial = new ArrayList<>(); + + final Set visitedRule = new HashSet<>(); + private final Set seenFull = new HashSet<>(); + private final Set seenPartial = new HashSet<>(); + + void add(final ScopeDependency dep) { + if (dep instanceof FullScopeDependency) { + final var fdep = (FullScopeDependency) dep; + if (!this.seenFull.contains(fdep.scopeName)) { + this.seenFull.add(fdep.scopeName); + this.full.add(fdep); + } + } else { + final var pdep = (PartialScopeDependency) dep; + if (!this.seenPartial.contains(pdep.toKey())) { + this.seenPartial.add(pdep.toKey()); + this.partial.add(pdep); + } + } + } + } + + final Set seenFullScopeRequests = new HashSet<>(); + final Set seenPartialScopeRequests = new HashSet<>(); + List queue = new ArrayList<>(); + + public final IGrammarRepository repo; + public final String initialScopeName; + + ScopeDependencyProcessor(final IGrammarRepository repo, final String initialScopeName) { + this.repo = repo; + this.initialScopeName = initialScopeName; + this.seenFullScopeRequests.add(initialScopeName); + this.queue.add(new FullScopeDependency(initialScopeName)); + } + + public void processQueue() { + final var q = queue; + queue = new ArrayList<>(); + + final var deps = new ScopeDependencyCollector(); + for (final var dep : q) { + collectDependenciesForDep(this.repo, this.initialScopeName, deps, dep); + } + + for (final var dep : deps.full) { + if (this.seenFullScopeRequests.contains(dep.scopeName)) { + // already processed + continue; + } + this.seenFullScopeRequests.add(dep.scopeName); + this.queue.add(dep); + } + + for (final var dep : deps.partial) { + if (this.seenFullScopeRequests.contains(dep.scopeName)) { + // already processed in full + continue; + } + if (this.seenPartialScopeRequests.contains(dep.toKey())) { + // already processed + continue; + } + this.seenPartialScopeRequests.add(dep.toKey()); + this.queue.add(dep); + } + } + + void collectDependenciesForDep( + final IGrammarRepository repo, + final String initialScopeName, + final ScopeDependencyCollector result, + final ScopeDependency dep) { + final var grammar = repo.lookup(dep.scopeName); + if (grammar == null) { + if (dep.scopeName.equals(initialScopeName)) { + throw new TMException("No grammar provided for <" + initialScopeName + ">"); + } + return; + } + + final var initialGrammar = repo.lookup(initialScopeName); + if (dep instanceof FullScopeDependency) { + collectDependencies(result, castNonNull(initialGrammar), grammar); + } else { + final var pdep = (PartialScopeDependency) dep; + collectSpecificDependencies(result, castNonNull(initialGrammar), grammar, pdep.include, null); + } + + final var injections = repo.injections(dep.scopeName); + if (injections != null) { + for (final var injection : injections) { + result.add(new FullScopeDependency(injection)); + } + } + } + + /** + * Collect a specific dependency from the grammar's repository + */ + void collectSpecificDependencies(final ScopeDependencyCollector result, final IRawGrammar baseGrammar, + final IRawGrammar selfGrammar, + final String include, @Nullable IRawRepository repository) { + if (repository == null && selfGrammar.isRepositorySet()) { + repository = selfGrammar.getRepository(); + } + if (repository != null) { + final var rule = repository.getRule(include); + if (rule != null) { + extractIncludedScopesInPatterns(result, baseGrammar, selfGrammar, List.of(rule), repository); + } + } + } + + /** + * Collects the list of all external included scopes in `grammar`. + */ + void collectDependencies(final ScopeDependencyCollector result, final IRawGrammar baseGrammar, + final IRawGrammar selfGrammar) { + final var patterns = selfGrammar.getPatterns(); + if (patterns != null) { + extractIncludedScopesInPatterns(result, baseGrammar, selfGrammar, patterns, selfGrammar.getRepository()); + } + final var injections = selfGrammar.getInjections(); + if (injections != null) { + extractIncludedScopesInPatterns(result, baseGrammar, selfGrammar, injections.values(), + selfGrammar.getRepository()); + } + } + + /** + * Fill in `result` all external included scopes in `patterns` + */ + void extractIncludedScopesInPatterns( + final ScopeDependencyCollector result, + final IRawGrammar baseGrammar, + final IRawGrammar selfGrammar, + final Collection patterns, + @Nullable final IRawRepository repository) { + for (final var pattern : patterns) { + if (result.visitedRule.contains(pattern)) { + continue; + } + result.visitedRule.add(pattern); + + final var patternRepository = pattern.getRepository() == null + ? repository + : IRawRepository.merge(repository, pattern.getRepository()); + final var patternPatterns = pattern.getPatterns(); + if (patternPatterns != null) { + extractIncludedScopesInPatterns(result, baseGrammar, selfGrammar, patternPatterns, patternRepository); + } + + final var include = pattern.getInclude(); + if (include == null) { + continue; + } + + if (include.equals(RawRepository.DOLLAR_BASE) || include.equals(baseGrammar.getScopeName())) { + collectDependencies(result, baseGrammar, baseGrammar); + } else if (include.equals(RawRepository.DOLLAR_SELF) || include.equals(selfGrammar.getScopeName())) { + collectDependencies(result, baseGrammar, selfGrammar); + } else if (include.charAt(0) == '#') { + collectSpecificDependencies(result, baseGrammar, selfGrammar, include.substring(1), patternRepository); + } else { + final var sharpIndex = include.indexOf('#'); + if (sharpIndex >= 0) { + final var scopeName = include.substring(0, sharpIndex); + final var includedName = include.substring(sharpIndex + 1); + if (scopeName.equals(baseGrammar.getScopeName())) { + collectSpecificDependencies(result, baseGrammar, baseGrammar, includedName, patternRepository); + } else if (scopeName.equals(selfGrammar.getScopeName())) { + collectSpecificDependencies(result, baseGrammar, selfGrammar, includedName, patternRepository); + } else { + result.add(new PartialScopeDependency(scopeName, include.substring(sharpIndex + 1))); + } + } else { + result.add(new FullScopeDependency(include)); + } + } + } + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/ScopeListElement.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/ScopeListElement.java index 59e1e47de..b1ed0b2b1 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/ScopeListElement.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/ScopeListElement.java @@ -9,145 +9,178 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.core.internal.grammar; - +package org.eclipse.tm4e.core.internal.grammar; + import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; -import org.eclipse.tm4e.core.theme.FontStyle; -import org.eclipse.tm4e.core.theme.ThemeTrieElementRule; - -public class ScopeListElement { - - public final ScopeListElement parent; - public final String scope; - public final int metadata; - - public ScopeListElement(ScopeListElement parent, String scope, int metadata) { - this.parent = parent; - this.scope = scope; - this.metadata = metadata; - } - - private static boolean equals(ScopeListElement a, ScopeListElement b) { - if (a == b) { - return true; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.theme.FontStyle; +import org.eclipse.tm4e.core.internal.theme.ThemeTrieElementRule; + +import com.google.common.base.Splitter; + +/** + * @see + * https://github.com/Microsoft/vscode-textmate/blob/main/src/grammar.ts + * + */ +public final class ScopeListElement { + + private static final Splitter BY_SPACE_SPLITTER = Splitter.on(' '); + + @Nullable + private final ScopeListElement parent; + private final String scope; + final int metadata; + + public ScopeListElement(@Nullable final ScopeListElement parent, final String scope, final int metadata) { + this.parent = parent; + this.scope = scope; + this.metadata = metadata; + } + + private static boolean structuralEquals(@Nullable ScopeListElement a, @Nullable ScopeListElement b) { + do { + if (a == b) { + return true; + } + + if (a == null && b == null) { + // End of list reached for both + return true; + } + + if (a == null || b == null) { + // End of list reached only for one + return false; + } + + if (!Objects.equals(a.scope, b.scope) || a.metadata != b.metadata) { + return false; + } + + // Go to previous pair + a = a.parent; + b = b.parent; + } while (true); + } + + private static boolean equals(@Nullable final ScopeListElement a, @Nullable final ScopeListElement b) { + if (a == b) { + return true; } if (a == null || b == null) { return false; - } - return Objects.equals(a.scope, b.scope) && a.metadata == b.metadata && equals(a.parent, b.parent); - } + } + return structuralEquals(a, b); + } + + @Override + public boolean equals(@Nullable final Object other) { + if (other == null || other.getClass() != ScopeListElement.class) { + return false; + } + return equals(this, (ScopeListElement) other); + } + + @Override + public int hashCode() { + return Objects.hash(parent, scope, metadata); + } + + private static boolean matchesScope(final String scope, final String selector, final String selectorWithDot) { + return (selector.equals(scope) || scope.startsWith(selectorWithDot)); + } - @Override - public boolean equals(Object other) { - if (other == this) { + /** + * implementation differs from upstream in that it is prevents potential NPEs/IndexOutOfBoundExceptions + */ + private static boolean matches(@Nullable ScopeListElement target, @Nullable final List parentScopes) { + if (parentScopes == null || parentScopes.isEmpty()) { return true; } - if (other == null) { + + if (target == null) { return false; } - if (!(other instanceof ScopeListElement)) { + + parent_scopes_loop: for (final String selector : parentScopes) { + final String selectorWithDot = selector + '.'; + + while (target != null) { + if (matchesScope(target.scope, selector, selectorWithDot)) { + // match for current parent scope found, continue with checking next parent scope + continue parent_scopes_loop; + } + target = target.parent; + } + // no match for current parent scope found, early exit return false; - } - return ScopeListElement.equals(this, (ScopeListElement)other); + } + + // matches for all parent scopes found + return true; + } + + public static int mergeMetadata(final int metadata, @Nullable final ScopeListElement scopesList, + @Nullable final ScopeMetadata source) { + if (source == null) { + return metadata; + } + + int fontStyle = FontStyle.NotSet; + int foreground = 0; + int background = 0; + + if (source.themeData != null) { + // Find the first themeData that matches + for (final ThemeTrieElementRule themeData : source.themeData) { + if (matches(scopesList, themeData.parentScopes)) { + fontStyle = themeData.fontStyle; + foreground = themeData.foreground; + background = themeData.background; + break; + } + } + } + + return StackElementMetadata.set(metadata, source.languageId, source.tokenType, null, fontStyle, foreground, + background); + } + + private static ScopeListElement push(ScopeListElement target, final Grammar grammar, + final Iterable scopes) { + for (final String scope : scopes) { + final var rawMetadata = grammar.getMetadataForScope(scope); + final int metadata = ScopeListElement.mergeMetadata(target.metadata, target, rawMetadata); + target = new ScopeListElement(target, scope, metadata); + } + return target; + } + + ScopeListElement push(final Grammar grammar, @Nullable final String scope) { + if (scope == null) { + return this; + } + + return ScopeListElement.push(this, grammar, BY_SPACE_SPLITTER.split(scope)); + } + + private static List generateScopes(@Nullable ScopeListElement scopesList) { + final var result = new ArrayList(); + while (scopesList != null) { + result.add(scopesList.scope); + scopesList = scopesList.parent; + } + Collections.reverse(result); + return result; } - @Override public int hashCode() { - return Objects.hash(scope, metadata, parent); + List generateScopes() { + return ScopeListElement.generateScopes(this); } - - - private static boolean matchesScope(String scope, String selector, String selectorWithDot) { - return (selector.equals(scope) || scope.startsWith(selectorWithDot)); - } - - private static boolean matches(ScopeListElement target, List parentScopes) { - if (parentScopes == null) { - return true; - } - - int len = parentScopes.size(); - int index = 0; - String selector = parentScopes.get(index); - String selectorWithDot = selector + "."; - - while (target != null) { - if (matchesScope(target.scope, selector, selectorWithDot)) { - index++; - if (index == len) { - return true; - } - selector = parentScopes.get(index); - selectorWithDot = selector + '.'; - } - target = target.parent; - } - - return false; - } - - public static int mergeMetadata(int metadata, ScopeListElement scopesList, ScopeMetadata source) { - if (source == null) { - return metadata; - } - - int fontStyle = FontStyle.NotSet; - int foreground = 0; - int background = 0; - - if (source.themeData != null) { - // Find the first themeData that matches - for (ThemeTrieElementRule themeData : source.themeData) { - if (matches(scopesList, themeData.parentScopes)) { - fontStyle = themeData.fontStyle; - foreground = themeData.foreground; - background = themeData.background; - break; - } - } - } - - return StackElementMetadata.set(metadata, source.languageId, source.tokenType, fontStyle, foreground, - background); - } - - private static ScopeListElement push(ScopeListElement target, Grammar grammar, List scopes) { - for (String scope : scopes) { - ScopeMetadata rawMetadata = grammar.getMetadataForScope(scope); - int metadata = ScopeListElement.mergeMetadata(target.metadata, target, rawMetadata); - target = new ScopeListElement(target, scope, metadata); - } - return target; - } - - public ScopeListElement push(Grammar grammar, String scope) { - if (scope == null) { - return this; - } - if (scope.indexOf(' ') >= 0) { - // there are multiple scopes to push - return ScopeListElement.push(this, grammar, Arrays.asList(scope.split(" ")));// scope.split(/ - // /g)); - } - // there is a single scope to push - return ScopeListElement.push(this, grammar, Arrays.asList(scope)); - } - - private static List generateScopes(ScopeListElement scopesList) { - List result = new ArrayList<>(); - while (scopesList != null) { - result.add(scopesList.scope); - scopesList = scopesList.parent; - } - Collections.reverse(result); - return result; - } - - public List generateScopes() { - return ScopeListElement.generateScopes(this); - } -} +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/ScopeMetadata.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/ScopeMetadata.java index fab90e9b5..9c66f1652 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/ScopeMetadata.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/ScopeMetadata.java @@ -9,23 +9,28 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.core.internal.grammar; - -import java.util.List; - -import org.eclipse.tm4e.core.theme.ThemeTrieElementRule; - -public class ScopeMetadata { - - public final String scopeName; - public final int languageId; - public final int tokenType; - public final List themeData; - - public ScopeMetadata(String scopeName, int languageId, int tokenType, List themeData) { - this.scopeName = scopeName; - this.languageId = languageId; - this.tokenType = tokenType; - this.themeData = themeData; - } -} +package org.eclipse.tm4e.core.internal.grammar; + +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.theme.ThemeTrieElementRule; + +public final class ScopeMetadata { + + final String scopeName; + final int languageId; + final int /*OptionalStandardTokenType*/ tokenType; + + @Nullable + final List themeData; + + public ScopeMetadata(final String scopeName, final int languageId, + final int /*OptionalStandardTokenType*/ tokenType, + @Nullable final List themeData) { + this.scopeName = scopeName; + this.languageId = languageId; + this.tokenType = tokenType; + this.themeData = themeData; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/ScopeMetadataProvider.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/ScopeMetadataProvider.java index b3d8b0180..7cb9f736c 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/ScopeMetadataProvider.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/ScopeMetadataProvider.java @@ -9,169 +9,152 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.core.internal.grammar; - -import java.util.Arrays; +package org.eclipse.tm4e.core.internal.grammar; + +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tm4e.core.TMException; -import org.eclipse.tm4e.core.theme.IThemeProvider; -import org.eclipse.tm4e.core.theme.ThemeTrieElementRule; - -public class ScopeMetadataProvider { - - private static final ScopeMetadata _NULL_SCOPE_METADATA = new ScopeMetadata("", 0, StandardTokenType.Other, null); - - private static final Pattern STANDARD_TOKEN_TYPE_REGEXP = Pattern.compile("\\b(comment|string|regex)\\b"); - private static final String COMMENT_TOKEN_TYPE = "comment"; - private static final String STRING_TOKEN_TYPE = "string"; - private static final String REGEX_TOKEN_TYPE = "regex"; - - private final int initialLanguage; - private final IThemeProvider themeProvider; - private final Map cache; - private ScopeMetadata defaultMetaData; - private final Map embeddedLanguages; - private Pattern embeddedLanguagesRegex; - - public ScopeMetadataProvider(int initialLanguage, IThemeProvider themeProvider, - Map embeddedLanguages) { - this.initialLanguage = initialLanguage; - this.themeProvider = themeProvider; - this.cache = new HashMap<>(); - this.onDidChangeTheme(); - - // embeddedLanguages handling - this.embeddedLanguages = new HashMap<>(); - if (embeddedLanguages != null) { - // If embeddedLanguages are configured, fill in - // `this._embeddedLanguages` - Set> languages = embeddedLanguages.entrySet(); - for (Entry language : languages) { - String scope = language.getKey(); - int languageId = language.getValue(); - /* - * if (typeof language !== 'number' || language === 0) { - * console.warn('Invalid embedded language found at scope ' + - * scope + ': <<' + language + '>>'); // never hurts to be too - * careful continue; } - */ - this.embeddedLanguages.put(scope, languageId); - } - } - - // create the regex - Set escapedScopes = this.embeddedLanguages.keySet().stream() - .map(ScopeMetadataProvider::escapeRegExpCharacters) - .collect(Collectors.toSet()); - if (escapedScopes.isEmpty()) { - // no scopes registered - this.embeddedLanguagesRegex = null; - } else { - // TODO!!! - this.embeddedLanguagesRegex = null; - // escapedScopes.sort(); - // escapedScopes.reverse(); - // this._embeddedLanguagesRegex = new - // RegExp(`^((${escapedScopes.join(')|(')}))($|\\.)`, ''); - } - } - -public void onDidChangeTheme() { - this.cache.clear(); - this.defaultMetaData = new ScopeMetadata( - "", - this.initialLanguage, - StandardTokenType.Other, - Arrays.asList(this.themeProvider.getDefaults()) - ); -} - - public ScopeMetadata getDefaultMetadata() { - return this.defaultMetaData; - } - - /** - * Escapes regular expression characters in a given string - */ - private static String escapeRegExpCharacters(String value) { - // TODO!!! - return value; //value.replace(/[\-\\\{\}\*\+\?\|\^\$\.\,\[\]\(\)\#\s]/g, '\\$&'); - } - - public ScopeMetadata getMetadataForScope(String scopeName) { - if (scopeName == null) { - return ScopeMetadataProvider._NULL_SCOPE_METADATA; - } - ScopeMetadata value = this.cache.get(scopeName); - if (value != null) { - return value; - } - value = this.doGetMetadataForScope(scopeName); - this.cache.put(scopeName, value); - return value; - } - - private ScopeMetadata doGetMetadataForScope(String scopeName) { - int languageId = this.scopeToLanguage(scopeName); - int standardTokenType = ScopeMetadataProvider.toStandardTokenType(scopeName); - List themeData = this.themeProvider.themeMatch(scopeName); - - return new ScopeMetadata(scopeName, languageId, standardTokenType, themeData); - } - - /** - * Given a produced TM scope, return the language that token describes or - * null if unknown. e.g. source.html => html, source.css.embedded.html => - * css, punctuation.definition.tag.html => null - */ - private int scopeToLanguage(String scope) { - if (scope == null) { - return 0; - } - if (this.embeddedLanguagesRegex == null) { - // no scopes registered - return 0; - } - - // TODO!!!! - - /*let m = scope.match(this._embeddedLanguagesRegex); - if (!m) { - // no scopes matched - return 0; - } - - let language = this._embeddedLanguages[m[1]] || 0; - if (!language) { - return 0; - } - - return language;*/ - return 0; - } - - private static int toStandardTokenType(String tokenType) { - Matcher m = STANDARD_TOKEN_TYPE_REGEXP.matcher(tokenType); // tokenType.match(ScopeMetadataProvider.STANDARD_TOKEN_TYPE_REGEXP); - if (!m.find()) { - return StandardTokenType.Other; - } - String group = m.group(); - if (COMMENT_TOKEN_TYPE.equals(group)) { - return StandardTokenType.Comment; - } else if (STRING_TOKEN_TYPE.equals(group)) { - return StandardTokenType.String; - } - if (REGEX_TOKEN_TYPE.equals(group)) { - return StandardTokenType.RegEx; - } - throw new TMException("Unexpected match for standard token type!"); - } -} +import org.eclipse.tm4e.core.internal.theme.IThemeProvider; +import org.eclipse.tm4e.core.internal.theme.ThemeTrieElementRule; +import org.eclipse.tm4e.core.internal.utils.RegexSource; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/grammar.ts + */ +final class ScopeMetadataProvider { + + private static final ScopeMetadata NULL_SCOPE_METADATA = new ScopeMetadata("", 0, 0, null); + + private static final Pattern STANDARD_TOKEN_TYPE_REGEXP = Pattern.compile("\\b(comment|string|regex)\\b"); + private static final String COMMENT_TOKEN_TYPE = "comment"; + private static final String STRING_TOKEN_TYPE = "string"; + private static final String REGEX_TOKEN_TYPE = "regex"; + private static final String META_EMBEDDED_TOKEN_TYPE = "meta.embedded"; + + private final int initialLanguage; + private final IThemeProvider themeProvider; + private final Map cache = new HashMap<>(); + + private ScopeMetadata defaultMetaData; + + private final Map embeddedLanguages = new HashMap<>(); + + @Nullable + private Pattern embeddedLanguagesRegex; + + ScopeMetadataProvider(final int initialLanguage, final IThemeProvider themeProvider, + @Nullable final Map embeddedLanguages) { + this.initialLanguage = initialLanguage; + this.themeProvider = themeProvider; + this.defaultMetaData = new ScopeMetadata( + "", + this.initialLanguage, + OptionalStandardTokenType.NotSet, + List.of(this.themeProvider.getDefaults())); + + // embeddedLanguages handling + if (embeddedLanguages != null) { + // If embeddedLanguages are configured, fill in `this.embeddedLanguages` + this.embeddedLanguages.putAll(embeddedLanguages); + } + + // create the regex + final var escapedScopes = this.embeddedLanguages.keySet().stream() + .map(RegexSource::escapeRegExpCharacters) + .collect(Collectors.toList()); + if (escapedScopes.isEmpty()) { + // no scopes registered + this.embeddedLanguagesRegex = null; + } else { + this.embeddedLanguagesRegex = Pattern.compile("^((" + + escapedScopes.stream().sorted(Collections.reverseOrder()).collect(Collectors.joining(")|(")) + + "))($|\\.)"); + } + } + + void onDidChangeTheme() { + this.cache.clear(); + this.defaultMetaData = new ScopeMetadata( + "", + this.initialLanguage, + OptionalStandardTokenType.NotSet, + List.of(this.themeProvider.getDefaults())); + } + + ScopeMetadata getDefaultMetadata() { + return this.defaultMetaData; + } + + ScopeMetadata getMetadataForScope(@Nullable final String scopeName) { + if (scopeName == null) { + return ScopeMetadataProvider.NULL_SCOPE_METADATA; + } + var value = this.cache.get(scopeName); + if (value != null) { + return value; + } + value = this.doGetMetadataForScope(scopeName); + this.cache.put(scopeName, value); + return value; + } + + private ScopeMetadata doGetMetadataForScope(final String scopeName) { + final int languageId = this.scopeToLanguage(scopeName); + final int standardTokenType = ScopeMetadataProvider.toStandardTokenType(scopeName); + final List themeData = this.themeProvider.themeMatch(scopeName); + + return new ScopeMetadata(scopeName, languageId, standardTokenType, themeData); + } + + /** + * Given a produced TM scope, return the language that token describes or null if unknown. + * e.g. source.html => html, source.css.embedded.html => css, punctuation.definition.tag.html => null + */ + private int scopeToLanguage(@Nullable final String scope) { + if (scope == null) { + return 0; + } + + final var embeddedLanguagesRegex = this.embeddedLanguagesRegex; + if (embeddedLanguagesRegex == null) { + // no scopes registered + return 0; + } + + final var m = embeddedLanguagesRegex.matcher(scope); + if (!m.find()) { + // no scopes matched + return 0; + } + + return embeddedLanguages.getOrDefault(m.group(1), 0); + } + + private static int /*OptionalStandardTokenType*/ toStandardTokenType(final String tokenType) { + final var m = STANDARD_TOKEN_TYPE_REGEXP.matcher(tokenType); + if (!m.find()) { + return OptionalStandardTokenType.NotSet; + } + final String group = m.group(1); + switch (group) { + case COMMENT_TOKEN_TYPE: + return OptionalStandardTokenType.Comment; + case STRING_TOKEN_TYPE: + return OptionalStandardTokenType.String; + case REGEX_TOKEN_TYPE: + return OptionalStandardTokenType.RegEx; + case META_EMBEDDED_TOKEN_TYPE: + return OptionalStandardTokenType.Other; + default: + throw new TMException("Unexpected match for standard token type: " + group); + } + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/StackElement.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/StackElement.java new file mode 100644 index 000000000..7d1cbf435 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/StackElement.java @@ -0,0 +1,278 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Initial code from https://github.com/Microsoft/vscode-textmate/ + * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. + * Initial license: MIT + * + * Contributors: + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.grammar; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.grammar.IStackElement; +import org.eclipse.tm4e.core.internal.rule.IRuleRegistry; +import org.eclipse.tm4e.core.internal.rule.Rule; + +/** + * Represents a "pushed" state on the stack (as a linked list element). + * + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/grammar.ts + */ +public final class StackElement implements IStackElement { + + public static final StackElement NULL = new StackElement(null, 0, 0, 0, false, null, + new ScopeListElement(null, "", 0), new ScopeListElement(null, "", 0)); + + /** + * The position on the current line where this state was pushed. + * This is relevant only while tokenizing a line, to detect endless loops. + * Its value is meaningless across lines. + */ + private int enterPosition; + + /** + * The captured anchor position when this stack element was pushed. + * This is relevant only while tokenizing a line, to restore the anchor position when popping. + * Its value is meaningless across lines. + */ + private int anchorPos; + + /** + * The previous state on the stack (or null for the root state). + */ + @Nullable + final StackElement parent; + + /** + * The depth of the stack. + */ + final int depth; + + /** + * The state (rule) that this element represents. + */ + final int ruleId; + + /** + * The state has entered and captured \n. This means that the next line should have an anchorPosition of 0. + */ + final boolean beginRuleCapturedEOL; + + /** + * The "pop" (end) condition for this state in case that it was dynamically generated through captured text. + */ + @Nullable + final String endRule; + + /** + * The list of scopes containing the "name" for this state. + */ + final ScopeListElement nameScopesList; + + /** + * The list of scopes containing the "contentName" (besides "name") for this state. + * This list **must** contain as an element `scopeName`. + */ + final ScopeListElement contentNameScopesList; + + StackElement( + @Nullable final StackElement parent, + final int ruleId, + final int enterPos, + final int anchorPos, + final boolean beginRuleCapturedEOL, + @Nullable final String endRule, + final ScopeListElement nameScopesList, + final ScopeListElement contentNameScopesList) { + this.parent = parent; + depth = this.parent != null ? this.parent.depth + 1 : 1; + this.ruleId = ruleId; + enterPosition = enterPos; + this.anchorPos = anchorPos; + this.beginRuleCapturedEOL = beginRuleCapturedEOL; + this.endRule = endRule; + this.nameScopesList = nameScopesList; + this.contentNameScopesList = contentNameScopesList; + } + + /** + * A structural equals check. Does not take into account `scopes`. + */ + private static boolean structuralEquals(@Nullable StackElement a, @Nullable StackElement b) { + do { + if (a == b) { + return true; + } + + if (a == null && b == null) { + // End of list reached for both + return true; + } + + if (a == null || b == null) { + // End of list reached only for one + return false; + } + + if (a.depth != b.depth || a.ruleId != b.ruleId || !Objects.equals(a.endRule, b.endRule)) { + return false; + } + + // Go to previous pair + a = a.parent; + b = b.parent; + } while (true); + } + + @SuppressWarnings("null") + private static boolean equals(@Nullable final StackElement a, @Nullable final StackElement b) { + if (a == b) { + return true; + } + if (!structuralEquals(a, b)) { + return false; + } + return a.contentNameScopesList.equals(b.contentNameScopesList); + } + + @Override + public boolean equals(@Nullable final Object other) { + if (other == null || other.getClass() != StackElement.class) { + return false; + } + return equals(this, (StackElement) other); + } + + @Override + public int getDepth() { + return depth; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + Objects.hash(endRule, parent, contentNameScopesList); + result = prime * result + depth; + result = prime * result + ruleId; + return result; + } + + void reset() { + StackElement el = this; + while (el != null) { + el.enterPosition = -1; + el.anchorPos = -1; + el = el.parent; + } + } + + @Nullable + StackElement pop() { + return parent; + } + + StackElement safePop() { + if (parent != null) + return parent; + return this; + } + + StackElement push(final int ruleId, + final int enterPos, + final int anchorPos, + final boolean beginRuleCapturedEOL, + @Nullable final String endRule, + final ScopeListElement nameScopesList, + final ScopeListElement contentNameScopesList) { + return new StackElement(this, + ruleId, + enterPos, + anchorPos, + beginRuleCapturedEOL, + endRule, + nameScopesList, + contentNameScopesList); + } + + int getAnchorPos() { + return anchorPos; + } + + int getEnterPos() { + return enterPosition; + } + + Rule getRule(final IRuleRegistry grammar) { + return grammar.getRule(ruleId); + } + + private void appendString(final List res) { + if (parent != null) { + parent.appendString(res); + } + // , TODO-${this.nameScopesList}, TODO-${this.contentNameScopesList})`; + res.add("(" + ruleId + ")"); + } + + @Override + public String toString() { + final var r = new ArrayList(); + appendString(r); + return '[' + String.join(", ", r) + ']'; + } + + StackElement setContentNameScopesList(final ScopeListElement contentNameScopesList) { + if (this.contentNameScopesList.equals(contentNameScopesList)) { + return this; + } + return castNonNull(this.parent).push(this.ruleId, + this.enterPosition, + this.anchorPos, + this.beginRuleCapturedEOL, + this.endRule, + this.nameScopesList, + contentNameScopesList); + } + + StackElement setEndRule(final String endRule) { + if (this.endRule != null && this.endRule.equals(endRule)) { + return this; + } + return new StackElement(this.parent, + this.ruleId, + this.enterPosition, + this.anchorPos, + this.beginRuleCapturedEOL, + endRule, + this.nameScopesList, + this.contentNameScopesList); + } + + boolean hasSameRuleAs(final StackElement other) { + var el = this; + while (el != null && el.enterPosition == other.enterPosition) { + if (el.ruleId == other.ruleId) { + return true; + } + el = el.parent; + } + return false; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/StackElementMetadata.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/StackElementMetadata.java index 5b5e87f04..271686424 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/StackElementMetadata.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/StackElementMetadata.java @@ -1,70 +1,83 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.grammar; - -import org.eclipse.tm4e.core.grammar.StackElement; -import org.eclipse.tm4e.core.theme.FontStyle; - -/** - * - * Metadata for {@link StackElement}. - * - */ -public class StackElementMetadata { - - /** - * Content should be referenced statically - */ - private StackElementMetadata() { - } - - public static String toBinaryStr(int metadata) { - /* - * let r = metadata.toString(2); while (r.length < 32) { r = '0' + r; } - * return r; - */ - // TODO!!! - return null; - } - - public static int getLanguageId(int metadata) { - return (metadata & MetadataConsts.LANGUAGEID_MASK) >>> MetadataConsts.LANGUAGEID_OFFSET; - } - - public static int getTokenType(int metadata) { - return (metadata & MetadataConsts.TOKEN_TYPE_MASK) >>> MetadataConsts.TOKEN_TYPE_OFFSET; - } - - public static int getFontStyle(int metadata) { - return (metadata & MetadataConsts.FONT_STYLE_MASK) >>> MetadataConsts.FONT_STYLE_OFFSET; - } - - public static int getForeground(int metadata) { - return (metadata & MetadataConsts.FOREGROUND_MASK) >>> MetadataConsts.FOREGROUND_OFFSET; - } - - public static int getBackground(int metadata) { - return (metadata & MetadataConsts.BACKGROUND_MASK) >>> MetadataConsts.BACKGROUND_OFFSET; - } - - public static int set(int metadata, int languageId, int tokenType, int fontStyle, int foreground, int background) { - languageId = languageId == 0 ? StackElementMetadata.getLanguageId(metadata) : languageId; - tokenType = tokenType == StandardTokenType.Other ? StackElementMetadata.getTokenType(metadata) : tokenType; - fontStyle = fontStyle == FontStyle.NotSet ? StackElementMetadata.getFontStyle(metadata) : fontStyle; - foreground = foreground == 0 ? StackElementMetadata.getForeground(metadata) : foreground; - background = background == 0 ? StackElementMetadata.getBackground(metadata) : background; - return ((languageId << MetadataConsts.LANGUAGEID_OFFSET) | (tokenType << MetadataConsts.TOKEN_TYPE_OFFSET) - | (fontStyle << MetadataConsts.FONT_STYLE_OFFSET) | (foreground << MetadataConsts.FOREGROUND_OFFSET) - | (background << MetadataConsts.BACKGROUND_OFFSET)) >>> 0; - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.grammar; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.theme.FontStyle; + +/** + * Metadata for {@link StackElement}. + * + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/metadata.ts + */ +public final class StackElementMetadata { + + /** + * Content should be referenced statically + */ + private StackElementMetadata() { + } + + static String toBinaryStr(final int metadata) { + return new StringBuilder(Integer.toBinaryString(metadata)) + .insert(0, "0".repeat(Integer.numberOfLeadingZeros(metadata))) + .toString(); + } + + static int getLanguageId(final int metadata) { + return (metadata & MetadataConsts.LANGUAGEID_MASK) >>> MetadataConsts.LANGUAGEID_OFFSET; + } + + static int getTokenType(final int metadata) { + return (metadata & MetadataConsts.TOKEN_TYPE_MASK) >>> MetadataConsts.TOKEN_TYPE_OFFSET; + } + + static boolean containsBalancedBrackets(final int metadata) { + return (metadata & MetadataConsts.BALANCED_BRACKETS_MASK) != 0; + } + + static int getFontStyle(final int metadata) { + return (metadata & MetadataConsts.FONT_STYLE_MASK) >>> MetadataConsts.FONT_STYLE_OFFSET; + } + + public static int getForeground(final int metadata) { + return (metadata & MetadataConsts.FOREGROUND_MASK) >>> MetadataConsts.FOREGROUND_OFFSET; + } + + static int getBackground(final int metadata) { + return (metadata & MetadataConsts.BACKGROUND_MASK) >>> MetadataConsts.BACKGROUND_OFFSET; + } + + /** + * Updates the fields in `metadata`. + * A value of `0`, `NotSet` or `null` indicates that the corresponding field should be left as is. + */ + static int set(final int metadata, final int languageId, final /*OptionalStandardTokenType*/ int tokenType, + @Nullable final Boolean containsBalancedBrackets, final int fontStyle, final int foreground, final int background) { + final var _languageId = languageId == 0 ? getLanguageId(metadata) : languageId; + final var _tokenType = tokenType == OptionalStandardTokenType.NotSet ? getTokenType(metadata) : tokenType; + final var _containsBalancedBracketsBit = (containsBalancedBrackets == null ? containsBalancedBrackets(metadata) + : containsBalancedBrackets) ? 1 : 0; + final var _fontStyle = fontStyle == FontStyle.NotSet ? getFontStyle(metadata) : fontStyle; + final var _foreground = foreground == 0 ? getForeground(metadata) : foreground; + final var _background = background == 0 ? getBackground(metadata) : background; + + return ((_languageId << MetadataConsts.LANGUAGEID_OFFSET) + | (_tokenType << MetadataConsts.TOKEN_TYPE_OFFSET) + | (_containsBalancedBracketsBit << MetadataConsts.BALANCED_BRACKETS_OFFSET) + | (_fontStyle << MetadataConsts.FONT_STYLE_OFFSET) + | (_foreground << MetadataConsts.FOREGROUND_OFFSET) + | (_background << MetadataConsts.BACKGROUND_OFFSET)) >>> 0; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/StandardTokenType.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/StandardTokenType.java index c215e02bb..914406d18 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/StandardTokenType.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/StandardTokenType.java @@ -1,31 +1,29 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.grammar; - -/** - * Standard TextMate token type. - * - */ -public class StandardTokenType { - - /** - * Content should be accessed statically - */ - private StandardTokenType() { - } - - public static final int Other = 0; - public static final int Comment = 1; - public static final int String = 2; - public static final int RegEx = 4; - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.grammar; + +/** + * Standard TextMate token type. + */ +final class StandardTokenType { + + /** + * Content should be accessed statically + */ + private StandardTokenType() { + } + + static final int Other = 0; + static final int Comment = 1; + static final int String = 2; + static final int RegEx = 3; +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/Token.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/Token.java index 99f420aa3..59a310ca6 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/Token.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/Token.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,59 +11,55 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.grammar; - -import java.util.List; - -import org.eclipse.tm4e.core.grammar.IToken; - -class Token implements IToken { - - private int startIndex; - - private int endIndex; - - private List scopes; - - public Token(int startIndex, int endIndex, List scopes) { - this.startIndex = startIndex; - this.endIndex = endIndex; - this.scopes = scopes; - } - - @Override - public int getStartIndex() { - return startIndex; - } - - @Override - public void setStartIndex(int startIndex) { - this.startIndex = startIndex; - } - - @Override - public int getEndIndex() { - return endIndex; - } - - @Override - public List getScopes() { - return scopes; - } - - @Override - public String toString() { - StringBuilder s = new StringBuilder(); - s.append("{startIndex: "); - s.append(startIndex); - s.append(", endIndex: "); - s.append(endIndex); - s.append(", scopes: "); - s.append(scopes); - s.append("}"); - return s.toString(); - } -} + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.grammar; + +import java.util.List; + +import org.eclipse.tm4e.core.grammar.IToken; + +final class Token implements IToken { + + private int startIndex; + + private final int endIndex; + + private final List scopes; + + Token(final int startIndex, final int endIndex, final List scopes) { + this.startIndex = startIndex; + this.endIndex = endIndex; + this.scopes = scopes; + } + + @Override + public int getStartIndex() { + return startIndex; + } + + @Override + public void setStartIndex(final int startIndex) { + this.startIndex = startIndex; + } + + @Override + public int getEndIndex() { + return endIndex; + } + + @Override + public List getScopes() { + return scopes; + } + + @Override + public String toString() { + return "{" + + "startIndex: " + startIndex + + ", endIndex: " + endIndex + + ", scopes: " + scopes + + "}"; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/TokenTypeMatcher.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/TokenTypeMatcher.java new file mode 100644 index 000000000..66d4bd725 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/TokenTypeMatcher.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2022 Sebastian Thomschke and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Initial code from https://github.com/Microsoft/vscode-textmate/ + * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. + * Initial license: MIT + * + * Contributors: + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Sebastian Thomschke - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.grammar; + +import java.util.List; + +import org.eclipse.tm4e.core.internal.matcher.Matcher; + +public interface TokenTypeMatcher { + + Matcher> getMatcher(); + + int /*StandardTokenType*/ getType(); +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/TokenizeLineResult.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/TokenizeLineResult.java index a2853a066..574901605 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/TokenizeLineResult.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/TokenizeLineResult.java @@ -13,36 +13,32 @@ * Contributors: * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.grammar; - -import org.eclipse.tm4e.core.grammar.IToken; -import org.eclipse.tm4e.core.grammar.ITokenizeLineResult; -import org.eclipse.tm4e.core.grammar.StackElement; - -/** - * - * Result of the line tokenization implementation. - * - */ -public class TokenizeLineResult implements ITokenizeLineResult { - - private final IToken[] tokens; - private final StackElement ruleStack; - - public TokenizeLineResult(IToken[] tokens, StackElement ruleStack) { - this.tokens = tokens; - this.ruleStack = ruleStack; - } - - @Override - public IToken[] getTokens() { - return tokens; - } - - @Override - public StackElement getRuleStack() { - return ruleStack; - } - -} + */ +package org.eclipse.tm4e.core.internal.grammar; + +import org.eclipse.tm4e.core.grammar.IToken; +import org.eclipse.tm4e.core.grammar.ITokenizeLineResult; + +/** + * Result of the line tokenization implementation. + */ +final class TokenizeLineResult implements ITokenizeLineResult { + + private final IToken[] tokens; + private final StackElement ruleStack; + + TokenizeLineResult(final IToken[] tokens, final StackElement ruleStack) { + this.tokens = tokens; + this.ruleStack = ruleStack; + } + + @Override + public IToken[] getTokens() { + return tokens; + } + + @Override + public StackElement getRuleStack() { + return ruleStack; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/TokenizeLineResult2.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/TokenizeLineResult2.java index 3ec920c90..c81759308 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/TokenizeLineResult2.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/TokenizeLineResult2.java @@ -13,35 +13,31 @@ * Contributors: * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.grammar; - + */ +package org.eclipse.tm4e.core.internal.grammar; + import org.eclipse.tm4e.core.grammar.ITokenizeLineResult2; -import org.eclipse.tm4e.core.grammar.StackElement; - -/** - * - * Result of the line tokenization2 implementation. - * - */ -public class TokenizeLineResult2 implements ITokenizeLineResult2 { - - private final int[] tokens; - private final StackElement ruleStack; - - public TokenizeLineResult2(int[] tokens, StackElement ruleStack) { - this.tokens = tokens; - this.ruleStack = ruleStack; - } - - @Override - public int[] getTokens() { - return tokens; - } - - @Override - public StackElement getRuleStack() { - return ruleStack; - } - -} + +/** + * Result of the line tokenization2 implementation. + */ +final class TokenizeLineResult2 implements ITokenizeLineResult2 { + + private final int[] tokens; + private final StackElement ruleStack; + + TokenizeLineResult2(final int[] tokens, final StackElement ruleStack) { + this.tokens = tokens; + this.ruleStack = ruleStack; + } + + @Override + public int[] getTokens() { + return tokens; + } + + @Override + public StackElement getRuleStack() { + return ruleStack; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/package-info.java new file mode 100644 index 000000000..1e721f14a --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.core.internal.grammar; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/parser/PListGrammar.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/parser/PListGrammar.java deleted file mode 100644 index d9597bde0..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/parser/PListGrammar.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.grammar.parser; - -import java.util.Map; - -import org.eclipse.tm4e.core.internal.parser.PListObject; - -public class PListGrammar extends PListObject { - - public PListGrammar(PListObject parent, boolean valueAsArray) { - super(parent, valueAsArray); - } - - @Override - protected Map createRaw() { - return new Raw(); - } - -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/parser/Raw.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/parser/Raw.java deleted file mode 100644 index 7c5c15683..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/parser/Raw.java +++ /dev/null @@ -1,305 +0,0 @@ -/** - * Copyright (c) 2015-2019 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - * Pierre-Yves B. - Issue #221 NullPointerException when retrieving fileTypes - */ -package org.eclipse.tm4e.core.internal.grammar.parser; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.eclipse.tm4e.core.internal.types.IRawCaptures; -import org.eclipse.tm4e.core.internal.types.IRawGrammar; -import org.eclipse.tm4e.core.internal.types.IRawRepository; -import org.eclipse.tm4e.core.internal.types.IRawRule; -import org.eclipse.tm4e.core.internal.utils.CloneUtils; - -/** - * Raw - * - */ -public class Raw extends HashMap implements IRawRepository, IRawRule, IRawGrammar, IRawCaptures { - private static final String FIRST_LINE_MATCH = "firstLineMatch"; - private static final String FILE_TYPES = "fileTypes"; - private static final String SCOPE_NAME = "scopeName"; - private static final String APPLY_END_PATTERN_LAST = "applyEndPatternLast"; - private static final String REPOSITORY = "repository"; - private static final String INJECTION_SELECTOR = "injectionSelector"; - private static final String INJECTIONS = "injections"; - private static final String PATTERNS = "patterns"; - private static final String WHILE_CAPTURES = "whileCaptures"; - private static final String END_CAPTURES = "endCaptures"; - private static final String INCLUDE = "include"; - private static final String WHILE = "while"; - private static final String END = "end"; - private static final String BEGIN = "begin"; - private static final String CAPTURES = "captures"; - private static final String MATCH = "match"; - private static final String BEGIN_CAPTURES = "beginCaptures"; - private static final String CONTENT_NAME = "contentName"; - private static final String NAME = "name"; - private static final String ID = "id"; - private static final String DOLLAR_SELF = "$self"; - private static final String DOLLAR_BASE = "$base"; - private static final long serialVersionUID = -2306714541728887963L; - private List fileTypes; - - @Override - public IRawRule getProp(String name) { - return (IRawRule) super.get(name); - } - - @Override - public IRawRule getBase() { - return (IRawRule) super.get(DOLLAR_BASE); - } - - @Override - public void setBase(IRawRule base) { - super.put(DOLLAR_BASE, base); - } - - @Override - public IRawRule getSelf() { - return (IRawRule) super.get(DOLLAR_SELF); - } - - @Override - public void setSelf(IRawRule self) { - super.put(DOLLAR_SELF, self); - } - - @Override - public Integer getId() { - return (Integer) super.get(ID); - } - - @Override - public void setId(Integer id) { - super.put(ID, id); - } - - @Override - public String getName() { - return (String) super.get(NAME); - } - - @Override - public void setName(String name) { - super.put(NAME, name); - } - - @Override - public String getContentName() { - return (String) super.get(CONTENT_NAME); - } - - @Override - public void setContentName(String name) { - super.put(CONTENT_NAME, name); - } - - @Override - public String getMatch() { - return (String) super.get(MATCH); - } - - @Override - public void setMatch(String match) { - super.put(MATCH, match); - } - - @Override - public IRawCaptures getCaptures() { - updateCaptures(CAPTURES); - return (IRawCaptures) super.get(CAPTURES); - } - - private void updateCaptures(String name) { - Object captures = super.get(name); - if (captures instanceof List) { - Raw rawCaptures = new Raw(); - int i = 0; - for (Object capture : (List) captures) { - i++; - rawCaptures.put(i + "", capture); - } - super.put(name, rawCaptures); - } - } - - @Override - public void setCaptures(IRawCaptures captures) { - super.put(CAPTURES, captures); - } - - @Override - public String getBegin() { - return (String) super.get(BEGIN); - } - - @Override - public void setBegin(String begin) { - super.put(BEGIN, begin); - } - - @Override - public String getWhile() { - return (String) super.get(WHILE); - } - - @Override - public String getInclude() { - return (String) super.get(INCLUDE); - } - - @Override - public void setInclude(String include) { - super.put(INCLUDE, include); - } - - @Override - public IRawCaptures getBeginCaptures() { - updateCaptures(BEGIN_CAPTURES); - return (IRawCaptures) super.get(BEGIN_CAPTURES); - } - - @Override - public void setBeginCaptures(IRawCaptures beginCaptures) { - super.put(BEGIN_CAPTURES, beginCaptures); - } - - @Override - public String getEnd() { - return (String) super.get(END); - } - - @Override - public void setEnd(String end) { - super.put(END, end); - } - - @Override - public IRawCaptures getEndCaptures() { - updateCaptures(END_CAPTURES); - return (IRawCaptures) super.get(END_CAPTURES); - } - - @Override - public void setEndCaptures(IRawCaptures endCaptures) { - super.put(END_CAPTURES, endCaptures); - } - - @Override - public IRawCaptures getWhileCaptures() { - updateCaptures(WHILE_CAPTURES); - return (IRawCaptures) super.get(WHILE_CAPTURES); - } - - @Override - public Collection getPatterns() { - return (Collection) super.get(PATTERNS); - } - - @Override - public void setPatterns(Collection patterns) { - super.put(PATTERNS, patterns); - } - - @Override - public Map getInjections() { - return (Map) super.get(INJECTIONS); - } - - @Override - public String getInjectionSelector() { - return (String) super.get(INJECTION_SELECTOR); - } - - @Override - public IRawRepository getRepository() { - return (IRawRepository) super.get(REPOSITORY); - } - - @Override - public void setRepository(IRawRepository repository) { - super.put(REPOSITORY, repository); - } - - @Override - public boolean isApplyEndPatternLast() { - Object applyEndPatternLast = super.get(APPLY_END_PATTERN_LAST); - if (applyEndPatternLast == null) { - return false; - } - if (applyEndPatternLast instanceof Boolean) { - return (Boolean) applyEndPatternLast; - } - if (applyEndPatternLast instanceof Integer) { - return ((Integer) applyEndPatternLast).equals(1); - } - return false; - } - - @Override - public void setApplyEndPatternLast(boolean applyEndPatternLast) { - super.put(APPLY_END_PATTERN_LAST, applyEndPatternLast); - } - - @Override - public String getScopeName() { - return (String) super.get(SCOPE_NAME); - } - - @Override - public Collection getFileTypes() { - if(fileTypes==null) { - List list=new ArrayList<>(); - Collection unparsedFileTypes = (Collection) super.get(FILE_TYPES); - if (unparsedFileTypes != null) { - for(Object o: unparsedFileTypes) { - String str=o.toString(); - // #202 - if(str.startsWith(".")) { - str=str.substring(1); - } - list.add(str); - } - } - fileTypes=list; - } - return fileTypes; - } - - @Override - public String getFirstLineMatch() { - return (String) super.get(FIRST_LINE_MATCH); - } - - @Override - public IRawRule getCapture(String captureId) { - return getProp(captureId); - } - - @Override - public Iterator iterator() { - return super.keySet().iterator(); - } - - @Override - public Object clone() { - return CloneUtils.clone(this); - } - -} \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/reader/GrammarReader.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/reader/GrammarReader.java index c1e0b3acb..5c8dc42b8 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/reader/GrammarReader.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/reader/GrammarReader.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,59 +11,75 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.grammar.reader; - + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.grammar.reader; + import java.io.InputStream; -import org.eclipse.tm4e.core.internal.parser.json.JSONPListParser; -import org.eclipse.tm4e.core.internal.parser.xml.XMLPListParser; -import org.eclipse.tm4e.core.internal.types.IRawGrammar; +import org.eclipse.tm4e.core.internal.grammar.RawRule; +import org.eclipse.tm4e.core.internal.grammar.RawCaptures; +import org.eclipse.tm4e.core.internal.grammar.RawGrammar; +import org.eclipse.tm4e.core.internal.grammar.RawRepository; +import org.eclipse.tm4e.core.internal.parser.PListParser; +import org.eclipse.tm4e.core.internal.parser.PListParserJSON; +import org.eclipse.tm4e.core.internal.parser.PListParserXML; +import org.eclipse.tm4e.core.internal.parser.PListParserYAML; +import org.eclipse.tm4e.core.internal.parser.PListPath; +import org.eclipse.tm4e.core.internal.parser.PropertySettable; +import org.eclipse.tm4e.core.internal.types.IRawGrammar; /** * TextMate Grammar reader utilities. - * - */ -public class GrammarReader { + */ +public final class GrammarReader { - /** - * methods should be accessed statically - */ - private GrammarReader() { + public static final PropertySettable.Factory OBJECT_FACTORY = path -> { + if (path.size() == 0) { + return new RawGrammar(); + } + switch (path.last()) { + case RawRule.REPOSITORY: + return new RawRepository(); + case RawRule.BEGIN_CAPTURES: + case RawRule.CAPTURES: + case RawRule.END_CAPTURES: + case RawRule.WHILE_CAPTURES: + return new RawCaptures(); + } + return new RawRule(); + }; - } + private static final PListParser JSON_PARSER = new PListParserJSON<>(OBJECT_FACTORY); + private static final PListParser XML_PARSER = new PListParserXML<>(OBJECT_FACTORY); + private static final PListParser YAML_PARSER = new PListParserYAML<>(OBJECT_FACTORY); - public static final IGrammarParser XML_PARSER = new IGrammarParser() { + public static IRawGrammar readGrammarSync(final String filePath, final InputStream in) throws Exception { + return getGrammarParser(filePath).parse(in); + } - private XMLPListParser parser = new XMLPListParser<>(false); + private static PListParser getGrammarParser(final String filePath) { + final String extension = filePath.substring(filePath.lastIndexOf('.') + 1).trim().toLowerCase(); - @Override - public IRawGrammar parse(InputStream contents) throws Exception { - return parser.parse(contents); - } - }; + switch (extension) { - public static final IGrammarParser JSON_PARSER = new IGrammarParser() { + case "json": + return JSON_PARSER; - private JSONPListParser parser = new JSONPListParser<>(false); + case "yaml": + case "yaml-tmlanguage": + case "yml": + return YAML_PARSER; - @Override - public IRawGrammar parse(InputStream contents) throws Exception { - return parser.parse(contents); + default: + return XML_PARSER; } - }; - - public static IRawGrammar readGrammarSync(String filePath, InputStream in) throws Exception { - SyncGrammarReader reader = new SyncGrammarReader(in, getGrammarParser(filePath)); - return reader.load(); - } - - private static IGrammarParser getGrammarParser(String filePath) { - if (filePath.endsWith(".json")) { - return JSON_PARSER; - } - return XML_PARSER; - } -} + } + + /** + * methods should be accessed statically + */ + private GrammarReader() { + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/reader/IGrammarParser.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/reader/IGrammarParser.java deleted file mode 100644 index 1cf264b29..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/reader/IGrammarParser.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/Microsoft/vscode-textmate/ - * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. - * Initial license: MIT - * - * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.grammar.reader; - -import java.io.InputStream; - -import org.eclipse.tm4e.core.internal.types.IRawGrammar; - -/** - * TextMate Grammar parser. - * - */ -@FunctionalInterface -public interface IGrammarParser { - - IRawGrammar parse(InputStream contents) throws Exception; -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/reader/SyncGrammarReader.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/reader/SyncGrammarReader.java deleted file mode 100644 index 5f94d6630..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/reader/SyncGrammarReader.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/Microsoft/vscode-textmate/ - * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. - * Initial license: MIT - * - * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.grammar.reader; - -import java.io.InputStream; - -import org.eclipse.tm4e.core.internal.types.IRawGrammar; - -public class SyncGrammarReader { - - private InputStream in; - private IGrammarParser parser; - - SyncGrammarReader(InputStream in, IGrammarParser parser) { - this.in = in; - this.parser = parser; - } - - public IRawGrammar load() throws Exception { - return this.parser.parse(in); - } -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/reader/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/reader/package-info.java new file mode 100644 index 000000000..838a708c2 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/reader/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.core.internal.grammar.reader; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammars/SyncRegistry.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammars/SyncRegistry.java deleted file mode 100644 index 6ba91f8f8..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammars/SyncRegistry.java +++ /dev/null @@ -1,193 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/Microsoft/vscode-textmate/ - * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. - * Initial license: MIT - * - * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.grammars; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import org.eclipse.tm4e.core.grammar.GrammarHelper; -import org.eclipse.tm4e.core.grammar.IGrammar; -import org.eclipse.tm4e.core.grammar.IGrammarRepository; -import org.eclipse.tm4e.core.internal.grammar.Grammar; -import org.eclipse.tm4e.core.internal.grammar.parser.Raw; -import org.eclipse.tm4e.core.internal.types.IRawGrammar; -import org.eclipse.tm4e.core.internal.types.IRawRepository; -import org.eclipse.tm4e.core.internal.types.IRawRule; -import org.eclipse.tm4e.core.theme.IThemeProvider; -import org.eclipse.tm4e.core.theme.Theme; -import org.eclipse.tm4e.core.theme.ThemeTrieElementRule; - -public class SyncRegistry implements IGrammarRepository, IThemeProvider { - - private final Map grammars; - private final Map rawGrammars; - private final Map> injectionGrammars; - private Theme theme; - - public SyncRegistry(Theme theme) { - this.theme = theme; - this.grammars = new HashMap<>(); - this.rawGrammars = new HashMap<>(); - this.injectionGrammars = new HashMap<>(); - } - - public void setTheme(Theme theme) { - this.theme = theme; - this.grammars.values().forEach(grammar -> ((Grammar) grammar).onDidChangeTheme()); - } - - public Set getColorMap() { - return this.theme.getColorMap(); - } - - /** - * Add `grammar` to registry and return a list of referenced scope names - */ - public Collection addGrammar(IRawGrammar grammar, Collection injectionScopeNames) { - this.rawGrammars.put(grammar.getScopeName(), grammar); - Collection includedScopes = new ArrayList<>(); - collectIncludedScopes(includedScopes, grammar); - - if (injectionScopeNames != null) { - this.injectionGrammars.put(grammar.getScopeName(), injectionScopeNames); - injectionScopeNames.forEach(scopeName -> addIncludedScope(scopeName, includedScopes)); - } - return includedScopes; - } - - @Override - public IRawGrammar lookup(String scopeName) { - return this.rawGrammars.get(scopeName); - } - - @Override - public Collection injections(String targetScope) { - return this.injectionGrammars.get(targetScope); - } - - /** - * Get the default theme settings - */ - @Override - public ThemeTrieElementRule getDefaults() { - return this.theme.getDefaults(); - } - - /** - * Match a scope in the theme. - */ - @Override - public List themeMatch(String scopeName) { - return this.theme.match(scopeName); - } - - /** - * Lookup a grammar. - */ - public IGrammar grammarForScopeName(String scopeName, int initialLanguage, - Map embeddedLanguages) { - if (!this.grammars.containsKey(scopeName)) { - IRawGrammar rawGrammar = lookup(scopeName); - if (rawGrammar == null) { - return null; - } - this.grammars.put(scopeName, - GrammarHelper.createGrammar(rawGrammar, initialLanguage, embeddedLanguages, this, this)); - } - return this.grammars.get(scopeName); - } - - private static void collectIncludedScopes(Collection result, IRawGrammar grammar) { - if (grammar - .getPatterns() != null /* && Array.isArray(grammar.patterns) */) { - extractIncludedScopesInPatterns(result, grammar.getPatterns()); - } - - IRawRepository repository = grammar.getRepository(); - if (repository != null) { - extractIncludedScopesInRepository(result, repository); - } - - // remove references to own scope (avoid recursion) - result.remove(grammar.getScopeName()); - } - - /** - * Fill in `result` all external included scopes in `patterns` - */ - private static void extractIncludedScopesInPatterns(Collection result, Collection patterns) { - for (IRawRule pattern : patterns) { - Collection p = pattern.getPatterns(); - if (p != null) { - extractIncludedScopesInPatterns(result, p); - } - - String include = pattern.getInclude(); - if (include == null) { - continue; - } - - if (include.equals("$base") || include.equals("$self")) { - // Special includes that can be resolved locally in this grammar - continue; - } - - if (include.charAt(0) == '#') { - // Local include from this grammar - continue; - } - - int sharpIndex = include.indexOf('#'); - if (sharpIndex >= 0) { - addIncludedScope(include.substring(0, sharpIndex), result); - } else { - addIncludedScope(include, result); - } - } - } - - private static void addIncludedScope(String scopeName, Collection includedScopes) { - if (!includedScopes.contains(scopeName)) { - includedScopes.add(scopeName); - } - } - - /** - * Fill in `result` all external included scopes in `repository` - */ - private static void extractIncludedScopesInRepository(Collection result, IRawRepository repository) { - if (!(repository instanceof Raw)) { - return; - } - Raw rawRepository = (Raw)repository; - for (Entry entry : rawRepository.entrySet()) { - IRawRule rule = (IRawRule) entry.getValue(); - if (rule.getPatterns() != null) { - extractIncludedScopesInPatterns(result, rule.getPatterns()); - } - if (rule.getRepository() != null) { - extractIncludedScopesInRepository(result, rule.getRepository()); - } - } - } - -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/IMatchInjectionsResult.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/IMatchInjectionsResult.java deleted file mode 100644 index 53ccaf243..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/IMatchInjectionsResult.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/Microsoft/vscode-textmate/ - * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. - * Initial license: MIT - * - * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.matcher; - -public interface IMatchInjectionsResult extends IMatchResult { - - boolean isPriorityMatch(); - - -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/IMatchResult.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/IMatchResult.java deleted file mode 100644 index b5d9b8577..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/IMatchResult.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/Microsoft/vscode-textmate/ - * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. - * Initial license: MIT - * - * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.matcher; - -import org.eclipse.tm4e.core.internal.oniguruma.IOnigCaptureIndex; - -public interface IMatchResult { - - IOnigCaptureIndex[] getCaptureIndices(); - - int getMatchedRuleId(); - -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/IMatchesName.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/IMatchesName.java deleted file mode 100644 index 27f9b5e5c..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/IMatchesName.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/Microsoft/vscode-textmate/ - * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. - * Initial license: MIT - * - * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.matcher; - -import java.util.Collection; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -public interface IMatchesName { - - public static final IMatchesName> NAME_MATCHER = new IMatchesName>() { - - @Override - public boolean match(Collection identifers, List scopes) { - if (scopes.size() < identifers.size()) { - return false; - } - AtomicInteger lastIndex = new AtomicInteger(); - // every - return identifers.stream().allMatch(identifier -> { - for (int i = lastIndex.get(); i < scopes.size(); i++) { - if (scopesAreMatching(scopes.get(i), identifier)) { - lastIndex.incrementAndGet(); - return true; - } - } - return false; - }); - } - - private boolean scopesAreMatching(String thisScopeName, String scopeName) { - if (thisScopeName == null) { - return false; - } - if (thisScopeName.equals(scopeName)) { - return true; - } - int len = scopeName.length(); - return thisScopeName.length() > len && thisScopeName.substring(0, len).equals(scopeName) - && thisScopeName.charAt(len) == '.'; - } - - }; - - boolean match(Collection names, T scopes); - -} \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/Matcher.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/Matcher.java index 48e1f2dc4..a48c00bfa 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/Matcher.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/Matcher.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,171 +11,24 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java */ package org.eclipse.tm4e.core.internal.matcher; -import java.util.ArrayList; -import java.util.Collection; import java.util.List; -import java.util.function.Predicate; -import java.util.regex.Pattern; -/** - * Matcher utilities. - * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/matcher.ts - * - */ -public class Matcher implements Predicate { - - private static final Pattern IDENTIFIER_REGEXP = Pattern.compile("[\\w\\.:]+"); - - public static Collection>> createMatchers(String expression) { - return createMatchers(expression, IMatchesName.NAME_MATCHER); - } - - private static Collection> createMatchers(String selector, IMatchesName matchesName) { - return new Matcher(selector, matchesName).results; - } - - private final List> results; - private final Tokenizer tokenizer; - private final IMatchesName matchesName; - private String token; - - public Matcher(String expression, IMatchesName matchesName) { - this.results = new ArrayList<>(); - this.tokenizer = new Tokenizer(expression); - this.matchesName = matchesName; - - this.token = tokenizer.next(); - while (token != null) { - int priority = 0; - if (token.length() == 2 && token.charAt(1) == ':') { - switch (token.charAt(0)) { - case 'R': - priority = 1; - break; - case 'L': - priority = -1; - break; - default: - // console.log(`Unknown priority ${token} in scope selector`); - } - token = tokenizer.next(); - } - Predicate matcher = parseConjunction(); - if (matcher != null) { - results.add(new MatcherWithPriority(matcher, priority)); - } - if (!",".equals(token)) { - break; - } - token = tokenizer.next(); - } - } +@FunctionalInterface +public interface Matcher { - private Predicate parseInnerExpression() { - List> matchers = new ArrayList<>(); - Predicate matcher = parseConjunction(); - while (matcher != null) { - matchers.add(matcher); - if (token.equals("|") || token.equals(",")) { - do { - token = tokenizer.next(); - } while (token.equals("|") || token.equals(",")); // ignore subsequent - // commas - } else { - break; - } - matcher = parseConjunction(); - } - // some (or) - return matcherInput -> { - for (Predicate matcher1 : matchers) { - if (matcher1.test(matcherInput)) { - return true; - } - } - return false; - }; + public static List>> createMatchers(final String selector) { + return createMatchers(selector, NameMatcher.DEFAULT); } - private Predicate parseConjunction() { - List> matchers = new ArrayList<>(); - Predicate matcher = parseOperand(); - while (matcher != null) { - matchers.add(matcher); - matcher = parseOperand(); - } - // every (and) - return matcherInput -> { - for (Predicate matcher1 : matchers) { - if (!matcher1.test(matcherInput)) { - return false; - } - } - return true; - }; - } - - private Predicate parseOperand() { - if ("-".equals(token)) { - token = tokenizer.next(); - Predicate expressionToNegate = parseOperand(); - return matcherInput -> { - if (expressionToNegate == null) { - return false; - } - return !expressionToNegate.test(matcherInput); - }; - } - if ("(".equals(token)) { - token = tokenizer.next(); - Predicate expressionInParents = parseInnerExpression(); - if (")".equals(token)) { - token = tokenizer.next(); - } - return expressionInParents; - } - if (isIdentifier(token)) { - Collection identifiers = new ArrayList<>(); - do { - identifiers.add(token); - token = tokenizer.next(); - } while (isIdentifier(token)); - return matcherInput -> Matcher.this.matchesName.match(identifiers, matcherInput); - } - return null; - } - - private boolean isIdentifier(String token) { - return token != null && IDENTIFIER_REGEXP.matcher(token).matches(); - } - - @Override - public boolean test(T matcherInput) { - return false; - } - - private static class Tokenizer { - - private static final Pattern REGEXP = Pattern.compile("([LR]:|[\\w\\.:]+|[\\,\\|\\-\\(\\)])"); - - private java.util.regex.Matcher regex; - - public Tokenizer(String input) { - this.regex = REGEXP.matcher(input); - } - - public String next() { - if (regex.find()) { - return regex.group(); - } - return null; - } + public static List>> createMatchers(final String selector, + final NameMatcher> matchesName) { + return new MatcherBuilder<>(selector, matchesName).results; } -} \ No newline at end of file + boolean matches(T t); +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/MatcherBuilder.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/MatcherBuilder.java new file mode 100644 index 000000000..b450a3d5e --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/MatcherBuilder.java @@ -0,0 +1,199 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Initial code from https://github.com/Microsoft/vscode-textmate/ + * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. + * Initial license: MIT + * + * Contributors: + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.matcher; + +import static java.lang.System.Logger.Level.*; + +import java.lang.System.Logger; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * Matcher utilities. + * + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/matcher.ts + */ +final class MatcherBuilder { + + private static final Logger LOGGER = System.getLogger(MatcherBuilder.class.getName()); + + final List> results = new ArrayList<>(); + private final Tokenizer tokenizer; + private final NameMatcher matchesName; + + @Nullable + private String token; + + MatcherBuilder(final String selector, final NameMatcher matchesName) { + tokenizer = new Tokenizer(selector); + this.matchesName = matchesName; + + // defining local token variable for annotation-based null analysis + var token = this.token = tokenizer.next(); + while (token != null) { + int priority = 0; + if (token.length() == 2 && token.charAt(1) == ':') { + switch (token.charAt(0)) { + case 'R': + priority = 1; + break; + case 'L': + priority = -1; + break; + default: + LOGGER.log(WARNING, "Unknown priority %s in scope selector %s", token, selector); + } + this.token = tokenizer.next(); + } + final Matcher matcher = parseConjunction(); + results.add(new MatcherWithPriority<>(matcher, priority)); + if (!",".equals(this.token)) { + break; + } + token = this.token = tokenizer.next(); + } + } + + @Nullable + private Matcher parseOperand() { + if ("-".equals(token)) { + token = tokenizer.next(); + final var expressionToNegate = parseOperand(); + return matcherInput -> expressionToNegate != null && !expressionToNegate.matches(matcherInput); + } + + if ("(".equals(token)) { + token = tokenizer.next(); + final var expressionInParents = parseInnerExpression(); + if (")".equals(token)) { + token = tokenizer.next(); + } + return expressionInParents; + } + + // defining local token variable for annotation-based null analysis + var token = this.token; + if (token != null && isIdentifier(token)) { + final var identifiers = new ArrayList(); + do { + identifiers.add(token); + token = this.token = tokenizer.next(); + } while (token != null && isIdentifier(token)); + return matcherInput -> matchesName.matches(identifiers, matcherInput); + } + return null; + } + + private Matcher parseConjunction() { + final var matchers = new ArrayList>(); + Matcher matcher = parseOperand(); + while (matcher != null) { + matchers.add(matcher); + matcher = parseOperand(); + } + + // every (and) + return matcherInput -> { + // same as 'matchers.stream().allMatch(m -> m.test(matcherInput))' but more memory friendly + for (final Matcher matcher1 : matchers) { + if (!matcher1.matches(matcherInput)) { + return false; + } + } + return true; + }; + } + + private Matcher parseInnerExpression() { + final var matchers = new ArrayList>(); + Matcher matcher = parseConjunction(); + while (true) { + matchers.add(matcher); + if ("|".equals(token) || ",".equals(token)) { + do { + token = tokenizer.next(); + } while ("|".equals(token) || ",".equals(token)); // ignore subsequent commas + } else { + break; + } + matcher = parseConjunction(); + } + + // some (or) + return matcherInput -> { + // same as 'matchers.stream().anyMatch(m -> m.test(matcherInput))' but more memory friendly + for (final Matcher matcher1 : matchers) { + if (matcher1.matches(matcherInput)) { + return true; + } + } + return false; + }; + } + + /** + * https://github.com/microsoft/vscode-textmate/blob/master/src/matcher.ts#L89 + */ + private boolean isIdentifier(final String token) { + if (token.isEmpty()) + return false; + + /* Aprox. 2-3 times faster than: + * static final Pattern IDENTIFIER_REGEXP = Pattern.compile("[\\w\\.:]+"); + * IDENTIFIER_REGEXP.matcher(token).matches(); + * + * Aprox. 10% faster than: + * token.chars().allMatch(ch -> ... ) + */ + for (int i = 0; i < token.length(); i++) { + final char ch = token.charAt(i); + if (ch == '.' || ch == ':' || ch == '_' + || (ch >= 'a' && ch <= 'z') + || (ch >= 'A' && ch <= 'Z') + || (ch >= '0' && ch <= '9')) + continue; + return false; + } + return true; + } + + private static final class Tokenizer { + + /** + * https://github.com/microsoft/vscode-textmate/blob/master/src/matcher.ts#L94 + */ + static final Pattern TOKEN_PATTERN = Pattern.compile("([LR]:|[\\w\\.:][\\w\\.:\\-]*|[\\,\\|\\-\\(\\)])"); + + final java.util.regex.Matcher regex; + + Tokenizer(final String input) { + regex = TOKEN_PATTERN.matcher(input); + } + + @Nullable + String next() { + if (!regex.find()) { + return null; + } + return regex.group(); + } + } +} \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/MatcherWithPriority.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/MatcherWithPriority.java index 4af84d724..742865f40 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/MatcherWithPriority.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/MatcherWithPriority.java @@ -1,35 +1,28 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/Microsoft/vscode-textmate/ - * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. - * Initial license: MIT - * - * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.matcher; - -import java.util.function.Predicate; - -public class MatcherWithPriority { - - public final Predicate matcher; - public final int priority; - - /** - * @param matcher - * @param priority - */ - public MatcherWithPriority(Predicate matcher, int priority) { - this.matcher = matcher; - this.priority = priority; - } - -} +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Initial code from https://github.com/Microsoft/vscode-textmate/ + * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. + * Initial license: MIT + * + * Contributors: + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.matcher; + +public final class MatcherWithPriority { + + public final Matcher matcher; + public final int priority; + + MatcherWithPriority(final Matcher matcher, final int priority) { + this.matcher = matcher; + this.priority = priority; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/NameMatcher.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/NameMatcher.java new file mode 100644 index 000000000..5faca95c2 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/NameMatcher.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Initial code from https://github.com/Microsoft/vscode-textmate/ + * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. + * Initial license: MIT + * + * Contributors: + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.matcher; + +import java.util.Collection; +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/grammar.ts + */ +public interface NameMatcher { + + NameMatcher> DEFAULT = new NameMatcher<>() { + + @Override + public boolean matches(final Collection identifiers, final List scopes) { + if (scopes.size() < identifiers.size()) { + return false; + } + final int[] lastIndex = { 0 }; + return identifiers.stream().allMatch(identifier -> { + for (int i = lastIndex[0]; i < scopes.size(); i++) { + if (scopesAreMatching(scopes.get(i), identifier)) { + lastIndex[0]++; + return true; + } + } + return false; + }); + } + + private boolean scopesAreMatching(@Nullable final String thisScopeName, final String scopeName) { + if (thisScopeName == null) { + return false; + } + if (thisScopeName.equals(scopeName)) { + return true; + } + final int len = scopeName.length(); + return thisScopeName.length() > len + && thisScopeName.substring(0, len).equals(scopeName) + && thisScopeName.charAt(len) == '.'; + } + }; + + boolean matches(Collection names, T scopes); +} \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/package-info.java new file mode 100644 index 000000000..5fd900fb5 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/matcher/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.core.internal.matcher; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/DecodeMap.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/model/DecodeMap.java similarity index 51% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/DecodeMap.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/model/DecodeMap.java index 3500e4448..7859336c4 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/DecodeMap.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/model/DecodeMap.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,67 +11,67 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.model; - -import java.util.LinkedHashMap; -import java.util.Map; - -class DecodeMap { - - int lastAssignedId; - Map scopeToTokenIds; - Map tokenToTokenId; - Map tokenIdToToken; - TMTokenDecodeData prevToken;; - - public DecodeMap() { - this.lastAssignedId = 0; - this.scopeToTokenIds = new LinkedHashMap<>(); - this.tokenToTokenId = new LinkedHashMap<>(); - this.tokenIdToToken = new LinkedHashMap<>(); - this.prevToken = new TMTokenDecodeData(new String[0], new LinkedHashMap>()); - } - - public int[] getTokenIds(String scope) { - int[] tokens = this.scopeToTokenIds.get(scope); - if (tokens != null) { - return tokens; - } - String[] tmpTokens = scope.split("[.]"); - - tokens = new int[tmpTokens.length]; - for (int i = 0; i < tmpTokens.length; i++) { - String token = tmpTokens[i]; - Integer tokenId = this.tokenToTokenId.get(token); - if (tokenId == null) { - tokenId = (++this.lastAssignedId); - this.tokenToTokenId.put(token, tokenId); - this.tokenIdToToken.put(tokenId, token); - } - tokens[i] = tokenId; - } - - this.scopeToTokenIds.put(scope, tokens); - return tokens; - } - - public String getToken(Map tokenMap) { - StringBuilder result = new StringBuilder(); - boolean isFirst = true; - for (int i = 1; i <= this.lastAssignedId; i++) { - if (tokenMap.containsKey(i)) { - if (isFirst) { - isFirst = false; - result.append(this.tokenIdToToken.get(i)); - } else { - result.append('.'); - result.append(this.tokenIdToToken.get(i)); - } - } - } - return result.toString(); - } -} + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.model; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.eclipse.jdt.annotation.Nullable; + +import com.google.common.base.Splitter; + +public final class DecodeMap { + + private static final String[] EMPTY_STRING_ARRAY = new String[0]; + private static final Splitter BY_DOT_SPLITTER = Splitter.on('.'); + + private int lastAssignedId = 0; + private final Map scopeToTokenIds = new LinkedHashMap<>(); + private final Map tokenToTokenId = new LinkedHashMap<>(); + private final Map tokenIdToToken = new LinkedHashMap<>(); + public TMTokenDecodeData prevToken = new TMTokenDecodeData(EMPTY_STRING_ARRAY, + new LinkedHashMap<>()); + + public int[] getTokenIds(final String scope) { + int[] tokens = this.scopeToTokenIds.get(scope); + if (tokens != null) { + return tokens; + } + final String[] tmpTokens = BY_DOT_SPLITTER.splitToStream(scope).toArray(String[]::new); + + tokens = new int[tmpTokens.length]; + for (int i = 0; i < tmpTokens.length; i++) { + final String token = tmpTokens[i]; + Integer tokenId = this.tokenToTokenId.get(token); + if (tokenId == null) { + tokenId = (++this.lastAssignedId); + this.tokenToTokenId.put(token, tokenId); + this.tokenIdToToken.put(tokenId, token); + } + tokens[i] = tokenId; + } + + this.scopeToTokenIds.put(scope, tokens); + return tokens; + } + + public String getToken(final Map tokenMap) { + final StringBuilder result = new StringBuilder(); + boolean isFirst = true; + for (int i = 1; i <= this.lastAssignedId; i++) { + if (tokenMap.containsKey(i)) { + if (isFirst) { + isFirst = false; + result.append(this.tokenIdToToken.get(i)); + } else { + result.append('.'); + result.append(this.tokenIdToToken.get(i)); + } + } + } + return result.toString(); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ModelTokensChangedEventBuilder.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/model/ModelTokensChangedEventBuilder.java similarity index 65% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ModelTokensChangedEventBuilder.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/model/ModelTokensChangedEventBuilder.java index b3aac593b..1e934d3da 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ModelTokensChangedEventBuilder.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/model/ModelTokensChangedEventBuilder.java @@ -13,38 +13,44 @@ * Contributors: * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.model; - + */ +package org.eclipse.tm4e.core.internal.model; + +import static org.eclipse.tm4e.core.internal.utils.MoreCollections.*; import java.util.ArrayList; -import java.util.List; - -class ModelTokensChangedEventBuilder { - - private final ITMModel model; - private final List ranges; - - public ModelTokensChangedEventBuilder(ITMModel model) { - this.model = model; - this.ranges = new ArrayList<>(); - } - - public void registerChangedTokens(int lineNumber) { - Range previousRange = ranges.isEmpty() ? null : ranges.get(ranges.size() - 1); - - if (previousRange != null && previousRange.toLineNumber == lineNumber - 1) { - // extend previous range - previousRange.toLineNumber++; - } else { - // insert new range - ranges.add(new Range(lineNumber)); - } - } - - public ModelTokensChangedEvent build() { - if (this.ranges.isEmpty()) { - return null; - } - return new ModelTokensChangedEvent(ranges, model); - } -} +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.model.ITMModel; +import org.eclipse.tm4e.core.model.ModelTokensChangedEvent; +import org.eclipse.tm4e.core.model.Range; + +public final class ModelTokensChangedEventBuilder { + + private final ITMModel model; + private final List ranges = new ArrayList<>(); + + public ModelTokensChangedEventBuilder(final ITMModel model) { + this.model = model; + } + + public void registerChangedTokens(final int lineNumber) { + final Range previousRange = findLastElement(ranges); + + if (previousRange != null && previousRange.toLineNumber == lineNumber - 1) { + // extend previous range + previousRange.toLineNumber++; + } else { + // insert new range + ranges.add(new Range(lineNumber)); + } + } + + @Nullable + public ModelTokensChangedEvent build() { + if (this.ranges.isEmpty()) { + return null; + } + return new ModelTokensChangedEvent(ranges, model); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/TMTokenDecodeData.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/model/TMTokenDecodeData.java similarity index 84% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/TMTokenDecodeData.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/model/TMTokenDecodeData.java index 8009f583f..3525fbbeb 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/TMTokenDecodeData.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/model/TMTokenDecodeData.java @@ -13,19 +13,19 @@ * Contributors: * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.model; - -import java.util.Map; - -public class TMTokenDecodeData { - - public final String[] scopes; - public final Map> scopeTokensMaps; - - TMTokenDecodeData(String[] scopes, Map> scopeTokensMaps) { - this.scopes = scopes; - this.scopeTokensMaps = scopeTokensMaps; - } - -} + */ +package org.eclipse.tm4e.core.internal.model; + +import java.util.Map; + +public class TMTokenDecodeData { + + public final String[] scopes; + public final Map> scopeTokensMaps; + + public TMTokenDecodeData(final String[] scopes, final Map> scopeTokensMaps) { + this.scopes = scopes; + this.scopeTokensMaps = scopeTokensMaps; + } + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/IOnigCaptureIndex.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/IOnigCaptureIndex.java deleted file mode 100644 index 3cb78c456..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/IOnigCaptureIndex.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/atom/node-oniguruma - * Initial copyright Copyright (c) 2013 GitHub Inc. - * Initial license: MIT - * - * Contributors: - * - GitHub Inc.: Initial code, written in JavaScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.oniguruma; - -public interface IOnigCaptureIndex { - - int getIndex(); - - int getStart(); - - int getEnd(); - - int getLength(); - -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/IOnigNextMatchResult.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/IOnigNextMatchResult.java deleted file mode 100644 index d2ab77906..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/IOnigNextMatchResult.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/atom/node-oniguruma - * Initial copyright Copyright (c) 2013 GitHub Inc. - * Initial license: MIT - * - * Contributors: - * - GitHub Inc.: Initial code, written in JavaScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ - -package org.eclipse.tm4e.core.internal.oniguruma; - -public interface IOnigNextMatchResult { - - int getIndex(); - - IOnigCaptureIndex[] getCaptureIndices(); -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigCaptureIndex.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigCaptureIndex.java new file mode 100644 index 000000000..fbd4398d6 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigCaptureIndex.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Initial code from https://github.com/atom/node-oniguruma + * Initial copyright Copyright (c) 2013 GitHub Inc. + * Initial license: MIT + * + * Contributors: + * - GitHub Inc.: Initial code, written in JavaScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.oniguruma; + +import org.eclipse.jdt.annotation.Nullable; + +public final class OnigCaptureIndex { + + public final int index; + public final int start; + public final int end; + + OnigCaptureIndex(final int index, final int start, final int end) { + this.index = index; + this.start = start >= 0 ? start : 0; + this.end = end >= 0 ? end : 0; + } + + @Override + public boolean equals(@Nullable final Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + final var other = (OnigCaptureIndex) obj; + return end == other.end + && index == other.index + && start == other.start; + } + + public int getLength() { + return end - start; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + end; + result = prime * result + index; + result = prime * result + start; + return result; + } + + @Override + public String toString() { + return "{" + + "\"index\": " + index + + ", \"start\": " + start + + ", \"end\": " + end + + ", \"length\": " + getLength() + + "}"; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigNextMatchResult.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigNextMatchResult.java index e028bd2ec..ed96aa880 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigNextMatchResult.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigNextMatchResult.java @@ -1,122 +1,94 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/atom/node-oniguruma - * Initial copyright Copyright (c) 2013 GitHub Inc. - * Initial license: MIT - * - * Contributors: - * - GitHub Inc.: Initial code, written in JavaScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.oniguruma; - -class OnigNextMatchResult implements IOnigNextMatchResult { - - private final int index; - - private final IOnigCaptureIndex[] captureIndices; - - public OnigNextMatchResult(OnigResult result, OnigString source) { - this.index = result.getIndex(); - this.captureIndices = captureIndicesForMatch(result, source); - } - - @Override - public int getIndex() { - return index; - } - - @Override - public IOnigCaptureIndex[] getCaptureIndices() { - return captureIndices; - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - result.append("{\n"); - result.append(" \"index\": "); - result.append(getIndex()); - result.append(",\n"); - result.append(" \"captureIndices\": [\n"); - int i = 0; - for (IOnigCaptureIndex captureIndex : getCaptureIndices()) { - if (i > 0) { - result.append(",\n"); - } - result.append(" "); - result.append(captureIndex); - i++; - } - result.append("\n"); - result.append(" ]\n"); - result.append("}"); - return result.toString(); - } - - private static IOnigCaptureIndex[] captureIndicesForMatch(OnigResult result, OnigString source) { - int resultCount = result.count(); - IOnigCaptureIndex[] captures = new IOnigCaptureIndex[resultCount]; - for (int index = 0; index < resultCount; index++) { - int captureStart = source.convertUtf8OffsetToUtf16(result.locationAt(index)); - int captureEnd = source.convertUtf8OffsetToUtf16(result.locationAt(index) + result.lengthAt(index)); - captures[index] = new OnigCaptureIndex(index, captureStart, captureEnd); - } - return captures; - } - - private static class OnigCaptureIndex implements IOnigCaptureIndex { - - private final int index; - private final int start; - private final int end; - - public OnigCaptureIndex(int index, int start, int end) { - this.index = index; - this.start = start >= 0 ? start : 0; - this.end = end >= 0 ? end : 0; - } - - @Override - public int getIndex() { - return index; - } - - @Override - public int getStart() { - return start; - } - - @Override - public int getEnd() { - return end; - } - - @Override - public int getLength() { - return end - start; - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - result.append("{\"index\": "); - result.append(getIndex()); - result.append(", \"start\": "); - result.append(getStart()); - result.append(", \"end\": "); - result.append(getEnd()); - result.append(", \"length\": "); - result.append(getLength()); - result.append("}"); - return result.toString(); - } - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Initial code from https://github.com/atom/node-oniguruma + * Initial copyright Copyright (c) 2013 GitHub Inc. + * Initial license: MIT + * + * Contributors: + * - GitHub Inc.: Initial code, written in JavaScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.oniguruma; + +import java.util.Arrays; + +import org.eclipse.jdt.annotation.Nullable; + +public final class OnigNextMatchResult { + + private final int index; + private final OnigCaptureIndex[] captureIndices; + + OnigNextMatchResult(final OnigResult result, final OnigString source) { + this.index = result.getIndex(); + this.captureIndices = captureIndicesOfMatch(result, source); + } + + private OnigCaptureIndex[] captureIndicesOfMatch(final OnigResult result, final OnigString source) { + final int resultCount = result.count(); + final var captures = new OnigCaptureIndex[resultCount]; + for (int i = 0; i < resultCount; i++) { + final int loc = result.locationAt(i); + final int captureStart = source.getCharIndexOfByte(loc); + final int captureEnd = source.getCharIndexOfByte(loc + result.lengthAt(i)); + captures[i] = new OnigCaptureIndex(i, captureStart, captureEnd); + } + return captures; + } + + @Override + public boolean equals(@Nullable final Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + final var other = (OnigNextMatchResult) obj; + return index == other.index + && Arrays.equals(captureIndices, other.captureIndices); + } + + public OnigCaptureIndex[] getCaptureIndices() { + return captureIndices; + } + + public int getIndex() { + return index; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + index; + result = prime * result + Arrays.hashCode(captureIndices); + return result; + } + + @Override + public String toString() { + final var result = new StringBuilder("{\n"); + result.append(" \"index\": "); + result.append(getIndex()); + result.append(",\n"); + result.append(" \"captureIndices\": [\n"); + int i = 0; + for (final OnigCaptureIndex captureIndex : getCaptureIndices()) { + if (i > 0) { + result.append(",\n"); + } + result.append(" "); + result.append(captureIndex); + i++; + } + result.append("\n"); + result.append(" ]\n"); + result.append("}"); + return result.toString(); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigRegExp.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigRegExp.java index 98b5e0046..77269b77f 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigRegExp.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigRegExp.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,16 +11,18 @@ * Initial license: MIT * * Contributors: - * - GitHub Inc.: Initial code, written in JavaScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - * - Fabio Zadrozny - Convert uniqueId to Object (for identity compare) - * - Fabio Zadrozny - Fix recursion error on creation of OnigRegExp with unicode chars + * - GitHub Inc.: Initial code, written in JavaScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + * - Fabio Zadrozny - Convert uniqueId to Object (for identity compare) + * - Fabio Zadrozny - Fix recursion error on creation of OnigRegExp with unicode chars */ package org.eclipse.tm4e.core.internal.oniguruma; import java.nio.charset.StandardCharsets; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.TMException; import org.jcodings.specific.UTF8Encoding; import org.joni.Matcher; import org.joni.Option; @@ -28,45 +30,56 @@ import org.joni.Region; import org.joni.Syntax; import org.joni.WarnCallback; +import org.joni.exception.SyntaxException; /** * - * @see https://github.com/atom/node-oniguruma/blob/master/src/onig-reg-exp.cc - * + * @see + * github.com/atom/node-oniguruma/blob/master/src/onig-reg-exp.cc * */ -public class OnigRegExp { +final class OnigRegExp { + @Nullable private OnigString lastSearchString; - private int lastSearchPosition; + + private int lastSearchPosition = -1; + + @Nullable private OnigResult lastSearchResult; - private Regex regex; - public OnigRegExp(String source) { - lastSearchString = null; - lastSearchPosition = -1; - lastSearchResult = null; - byte[] pattern = source.getBytes(StandardCharsets.UTF_8); - this.regex = new Regex(pattern, 0, pattern.length, Option.CAPTURE_GROUP, UTF8Encoding.INSTANCE, Syntax.DEFAULT, - WarnCallback.DEFAULT); + private final Regex regex; + + OnigRegExp(final String source) { + final byte[] pattern = source.getBytes(StandardCharsets.UTF_8); + try { + regex = new Regex(pattern, 0, pattern.length, Option.CAPTURE_GROUP, UTF8Encoding.INSTANCE, Syntax.DEFAULT, + WarnCallback.DEFAULT); + } catch (final SyntaxException ex) { + throw new TMException("Parsing regex pattern \"" + source + "\" failed with " + ex, ex); + } } - public OnigResult search(OnigString str, int position) { - if (lastSearchString == str && lastSearchPosition <= position && - (lastSearchResult == null || lastSearchResult.locationAt(0) >= position)) { - return lastSearchResult; + @Nullable + OnigResult search(final OnigString str, final int position) { + final OnigResult theLastSearchResult = lastSearchResult; + if (lastSearchString == str + && lastSearchPosition <= position + && (theLastSearchResult == null || theLastSearchResult.locationAt(0) >= position)) { + return theLastSearchResult; } lastSearchString = str; lastSearchPosition = position; - lastSearchResult = search(str.utf8_value, position, str.utf8_value.length); + lastSearchResult = search(str.bytesUTF8, position, str.bytesCount); return lastSearchResult; } - private OnigResult search(byte[] data, int position, int end) { - Matcher matcher = regex.matcher(data); - int status = matcher.search(position, end, Option.DEFAULT); + @Nullable + private OnigResult search(final byte[] data, final int position, final int end) { + final Matcher matcher = regex.matcher(data); + final int status = matcher.search(position, end, Option.DEFAULT); if (status != Matcher.FAILED) { - Region region = matcher.getEagerRegion(); + final Region region = matcher.getEagerRegion(); return new OnigResult(region, -1); } return null; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigResult.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigResult.java index 172ff5449..70323d2f0 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigResult.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigResult.java @@ -14,49 +14,45 @@ * - GitHub Inc.: Initial code, written in JavaScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java */ - package org.eclipse.tm4e.core.internal.oniguruma; import org.joni.Region; -public class OnigResult { +final class OnigResult { private int indexInScanner; private final Region region; - public OnigResult(Region region, int indexInScanner) { + OnigResult(final Region region, final int indexInScanner) { this.region = region; this.indexInScanner = indexInScanner; } - public int getIndex() { + int getIndex() { return indexInScanner; } - public void setIndex(int index) { - this.indexInScanner = index; + void setIndex(final int index) { + indexInScanner = index; } - public int locationAt(int index) { - int bytes = region.beg[index]; + int locationAt(final int index) { + final int bytes = region.beg[index]; if (bytes > 0) { return bytes; - } else { - return 0; } + return 0; } - public int count() { + int count() { return region.numRegs; } - public int lengthAt(int index) { - int bytes = region.end[index] - region.beg[index]; + int lengthAt(final int index) { + final int bytes = region.end[index] - region.beg[index]; if (bytes > 0) { return bytes; - } else { - return 0; } + return 0; } - } diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigScanner.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigScanner.java index 428ac584e..4209e880e 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigScanner.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigScanner.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,30 +11,35 @@ * Initial license: MIT * * Contributors: - * - GitHub Inc.: Initial code, written in JavaScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java + * - GitHub Inc.: Initial code, written in JavaScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java */ - package org.eclipse.tm4e.core.internal.oniguruma; -public class OnigScanner { +import java.util.Collection; + +import org.eclipse.jdt.annotation.Nullable; + +public final class OnigScanner { private final OnigSearcher searcher; - public OnigScanner(String[] regexps) { - this.searcher = new OnigSearcher(regexps); + public OnigScanner(final Collection regexps) { + searcher = new OnigSearcher(regexps); } - public IOnigNextMatchResult findNextMatchSync(OnigString source, int charOffset) { - OnigResult bestResult = searcher.search(source, charOffset); + @Nullable + public OnigNextMatchResult findNextMatchSync(final OnigString source, final int charOffset) { + final OnigResult bestResult = searcher.search(source, charOffset); if (bestResult != null) { return new OnigNextMatchResult(bestResult, source); } return null; } - public IOnigNextMatchResult findNextMatchSync(String lin, int pos) { - return findNextMatchSync(new OnigString(lin), pos); + @Nullable + OnigNextMatchResult findNextMatchSync(final String lin, final int pos) { + return findNextMatchSync(OnigString.of(lin), pos); } } diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigSearcher.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigSearcher.java index e0a845665..d7309e6d0 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigSearcher.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigSearcher.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,49 +11,50 @@ * Initial license: MIT * * Contributors: - * - GitHub Inc.: Initial code, written in JavaScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java + * - GitHub Inc.: Initial code, written in JavaScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java */ - -package org.eclipse.tm4e.core.internal.oniguruma; - -import java.util.Arrays; +package org.eclipse.tm4e.core.internal.oniguruma; + +import java.util.Collection; import java.util.List; -import java.util.stream.Collectors; - -public class OnigSearcher { - - private final List regExps; - - public OnigSearcher(String[] regexps) { - this.regExps = Arrays.stream(regexps).map(OnigRegExp::new).collect(Collectors.toList()); - } - - public OnigResult search(OnigString source, int charOffset) { - int byteOffset = source.convertUtf16OffsetToUtf8(charOffset); - - int bestLocation = 0; - OnigResult bestResult = null; - int index = 0; - - for (OnigRegExp regExp : regExps) { - OnigResult result = regExp.search(source, byteOffset); - if (result != null && result.count() > 0) { - int location = result.locationAt(0); - - if (bestResult == null || location < bestLocation) { - bestLocation = location; - bestResult = result; - bestResult.setIndex(index); - } - - if (location == byteOffset) { - break; - } - } - index++; - } - return bestResult; - } - -} +import java.util.stream.Collectors; + +import org.eclipse.jdt.annotation.Nullable; + +final class OnigSearcher { + + private final List regExps; + + OnigSearcher(final Collection regExps) { + this.regExps = regExps.stream().map(OnigRegExp::new).collect(Collectors.toList()); + } + + @Nullable + OnigResult search(final OnigString source, final int charOffset) { + final int byteOffset = source.getByteIndexOfChar(charOffset); + + int bestLocation = 0; + OnigResult bestResult = null; + int index = 0; + + for (final OnigRegExp regExp : regExps) { + final OnigResult result = regExp.search(source, byteOffset); + if (result != null && result.count() > 0) { + final int location = result.locationAt(0); + + if (bestResult == null || location < bestLocation) { + bestLocation = location; + bestResult = result; + bestResult.setIndex(index); + } + + if (location == byteOffset) { + break; + } + } + index++; + } + return bestResult; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigString.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigString.java index b8c91e5b9..363e158c3 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigString.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/OnigString.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,116 +11,173 @@ * Initial license: MIT * * Contributors: - * - GitHub Inc.: Initial code, written in JavaScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - * - Fabio Zadrozny - Convert uniqueId to Object (for identity compare) - * - Fabio Zadrozny - Utilities to convert between utf-8 and utf-16 + * - GitHub Inc.: Initial code, written in JavaScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + * - Fabio Zadrozny - Convert uniqueId to Object (for identity compare) + * - Fabio Zadrozny - Utilities to convert between utf-8 and utf-16 */ - package org.eclipse.tm4e.core.internal.oniguruma; import java.nio.charset.StandardCharsets; import java.util.Arrays; +import org.eclipse.jdt.annotation.Nullable; import org.jcodings.specific.UTF8Encoding; /** * Oniguruma string. * - * @see https://github.com/atom/node-oniguruma/blob/master/src/onig-string.cc + * @see + * github.com/atom/node-oniguruma/blob/master/src/onig-string.cc * */ -public class OnigString { +public abstract class OnigString { - public final String string; - public final byte[] utf8_value; + /** + * Represents a string that contains multi-byte characters + */ + static final class MultiByteString extends OnigString { - private int[] charsPosFromBytePos; - private boolean computedOffsets; + /** + * For each byte holds the index of the char to which the byte belongs. + * E.g. in case of byteToCharOffsets[100] == 60 && byteToCharOffsets[101] == 60, + * the bytes at indexes 100 and 101 both belong to the same multi-byte character at index 60. + */ + private int @Nullable [] byteToCharOffsets; + private final int lastCharIndex; + private MultiByteString(final String str, final byte[] bytesUTF8) { + super(str, bytesUTF8); + lastCharIndex = str.length() - 1; + } - public OnigString(String str) { - this.string = str; - this.utf8_value = str.getBytes(StandardCharsets.UTF_8); - } + @Override + int getByteIndexOfChar(final int charIndex) { + if (charIndex == lastCharIndex + 1) { + // One off can happen when finding the end of a regexp (it's the right boundary). + return lastCharIndex + 1; + } - public int convertUtf16OffsetToUtf8(int posInChars) { - if(!computedOffsets) { - computeOffsets(); - } - if (charsPosFromBytePos == null) { - // Same conditions as code below, but taking into account that the - // bytes and chars len are the same. - if (posInChars < 0 || this.utf8_value.length == 0 || posInChars > this.utf8_value.length) { - throw new ArrayIndexOutOfBoundsException(posInChars); + if (charIndex < 0 || charIndex > lastCharIndex) { + throwOutOfBoundsException("Char", charIndex, 0, lastCharIndex); + } + if (charIndex == 0) { + return 0; } - return posInChars; - } - int[] charsLenInBytes = charsPosFromBytePos; - if (posInChars < 0 || charsLenInBytes.length == 0) { - throw new ArrayIndexOutOfBoundsException(posInChars); - } - if (posInChars == 0) { - return 0; + final int[] byteToCharOffsets = getByteToCharOffsets(); + int byteIndex = Arrays.binarySearch(byteToCharOffsets, charIndex); + while (byteIndex > 0 && byteToCharOffsets[byteIndex - 1] == charIndex) { + byteIndex--; + } + return byteIndex; } - int last = charsLenInBytes[charsLenInBytes.length - 1]; - if (last < posInChars) { - if (last == posInChars - 1) { - return charsLenInBytes.length; - } else { - throw new ArrayIndexOutOfBoundsException(posInChars); + private int[] getByteToCharOffsets() { + int[] offsets = byteToCharOffsets; + if (offsets == null) { + offsets = new int[bytesCount]; + int charIndex = 0; + int byteIndex = 0; + final int maxByteIndex = bytesCount - 1; + while (byteIndex <= maxByteIndex) { + final int charLenInBytes = UTF8Encoding.INSTANCE.length(bytesUTF8, byteIndex, bytesCount); + // same as "Arrays.fill(offsets, byteIndex, byteIndex + charLenInBytes, charIndex)" but faster + for (final int l = byteIndex + charLenInBytes; byteIndex < l; byteIndex++) { + offsets[byteIndex] = charIndex; + } + charIndex++; + } + byteToCharOffsets = offsets; } + return offsets; } - int index = Arrays.binarySearch(charsLenInBytes, posInChars); - while (index > 0) { - if (charsLenInBytes[index - 1] == posInChars) { - index--; - } else { - break; + @Override + int getCharIndexOfByte(final int byteIndex) { + if (byteIndex == bytesCount) { + // One off can happen when finding the end of a regexp (it's the right boundary). + return lastCharIndex + 1; + } + + if (byteIndex < 0 || byteIndex >= bytesCount) { + throwOutOfBoundsException("Byte", byteIndex, 0, bytesCount - 1); } + if (byteIndex == 0) { + return 0; + } + + return getByteToCharOffsets()[byteIndex]; } - return index; } - public int convertUtf8OffsetToUtf16(int posInBytes) { - if(!computedOffsets) { - computeOffsets(); - } - if (charsPosFromBytePos == null) { - return posInBytes; - } - if (posInBytes < 0) { - return posInBytes; + /** + * Represents a string is only composed of single-byte characters + */ + static final class SingleByteString extends OnigString { + + private SingleByteString(final String str, final byte[] bytesUTF8) { + super(str, bytesUTF8); } - if (posInBytes >= charsPosFromBytePos.length) { - //One off can happen when finding the end of a regexp (it's the right boundary). - return charsPosFromBytePos[posInBytes - 1] + 1; + + @Override + int getByteIndexOfChar(final int charIndex) { + if (charIndex == bytesCount) { + // One off can happen when finding the end of a regexp (it's the right boundary). + return charIndex; + } + + if (charIndex < 0 || charIndex >= bytesCount) { + throwOutOfBoundsException("Char", charIndex, 0, bytesCount - 1); + } + return charIndex; } - return charsPosFromBytePos[posInBytes]; - } - private void computeOffsets() { - if (this.utf8_value.length != this.string.length()) { - charsPosFromBytePos = new int[this.utf8_value.length]; - int bytesLen = 0;; - int charsLen = 0; - int length = this.utf8_value.length; - for (int i = 0; i < length;) { - int codeLen = UTF8Encoding.INSTANCE.length(this.utf8_value, i, length); - for (int i1 = 0; i1 < codeLen; i1++) { - charsPosFromBytePos[bytesLen + i1] = charsLen; - } - bytesLen += codeLen; - i += codeLen; - charsLen += 1; + @Override + int getCharIndexOfByte(final int byteIndex) { + if (byteIndex == bytesCount) { + // One off can happen when finding the end of a regexp (it's the right boundary). + return byteIndex; } - if(bytesLen != this.utf8_value.length) { - throw new AssertionError(bytesLen + " != "+this.utf8_value.length); + + if (byteIndex < 0 || byteIndex >= bytesCount) { + throwOutOfBoundsException("Byte", byteIndex, 0, bytesCount - 1); } + return byteIndex; } - computedOffsets = true; + } + + public static OnigString of(final String str) { + final byte[] bytesUtf8 = str.getBytes(StandardCharsets.UTF_8); + if (bytesUtf8.length == str.length()) { + return new SingleByteString(str, bytesUtf8); + } + return new MultiByteString(str, bytesUtf8); + } + + public final String string; + + public final int bytesCount; + final byte[] bytesUTF8; + + private OnigString(final String str, final byte[] bytesUTF8) { + string = str; + this.bytesUTF8 = bytesUTF8; + bytesCount = bytesUTF8.length; + } + + protected final String throwOutOfBoundsException(final String indexName, final int index, final int minIndex, + final int maxIndex) { + throw new ArrayIndexOutOfBoundsException( + indexName + " index " + index + " is out of range " + minIndex + ".." + maxIndex + " of " + this); + } + + abstract int getByteIndexOfChar(int charIndex); + + abstract int getCharIndexOfByte(int byteIndex); + + @Override + public String toString() { + return getClass().getSimpleName() + "[string=\"" + string + "\"]"; } } diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/package-info.java new file mode 100644 index 000000000..e57353dd1 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/oniguruma/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.core.internal.oniguruma; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PList.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PList.java deleted file mode 100644 index 273893144..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PList.java +++ /dev/null @@ -1,132 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.parser; - -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.tm4e.core.internal.grammar.parser.PListGrammar; -import org.eclipse.tm4e.core.internal.theme.PListTheme; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -public class PList extends DefaultHandler { - - private final boolean theme; - private final List errors; - private PListObject currObject; - private T result; - private StringBuilder text; - - public PList(boolean theme) { - this.theme = theme; - this.errors = new ArrayList<>(); - this.currObject = null; - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - if ("dict".equals(localName)) { - this.currObject = create(currObject, false); - } else if ("array".equals(localName)) { - this.currObject = create(currObject, true); - } else if ("key".equals(localName)) { - if (currObject != null) { - currObject.setLastKey(null); - } - } - this.text = new StringBuilder(""); - super.startElement(uri, localName, qName, attributes); - } - - private PListObject create(PListObject parent, boolean valueAsArray) { - if (theme) { - return new PListTheme(parent, valueAsArray); - } - return new PListGrammar(parent, valueAsArray); - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - endElement(localName); - super.endElement(uri, localName, qName); - } - - private void endElement(String tagName) { - Object value = null; - String text = this.text.toString(); - if ("key".equals(tagName)) { - if (currObject == null || currObject.isValueAsArray()) { - errors.add("key can only be used inside an open dict element"); - return; - } - currObject.setLastKey(text); - return; - } else if ("dict".equals(tagName) || "array".equals(tagName)) { - if (currObject == null) { - errors.add(tagName + " closing tag found, without opening tag"); - return; - } - value = currObject.getValue(); - currObject = currObject.parent; - } else if ("string".equals(tagName) || "data".equals(tagName)) { - value = text; - } else if ("date".equals(tagName)) { - // TODO : parse date - } else if ("integer".equals(tagName)) { - try { - value = Integer.parseInt(text); - } catch (NumberFormatException e) { - errors.add(text + " is not a integer"); - return; - } - } else if ("real".equals(tagName)) { - try { - value = Float.parseFloat(text); - } catch (NumberFormatException e) { - errors.add(text + " is not a float"); - return; - } - } else if ("true".equals(tagName)) { - value = true; - } else if ("false".equals(tagName)) { - value = false; - } else if ("plist".equals(tagName)) { - return; - } else { - errors.add("Invalid tag name: " + tagName); - return; - } - if (currObject == null) { - result = (T) value; - } else if (currObject.isValueAsArray()) { - currObject.addValue(value); - } else { - if (currObject.getLastKey() != null) { - currObject.addValue(value); - } else { - errors.add("Dictionary key missing for value " + value); - } - } - } - - @Override - public void characters(char[] ch, int start, int length) throws SAXException { - this.text.append(String.valueOf(ch, start, length)); - super.characters(ch, start, length); - } - - public T getResult() { - return result; - } -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListContentHandler.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListContentHandler.java new file mode 100644 index 000000000..ec8455282 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListContentHandler.java @@ -0,0 +1,233 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.parser; + +import static java.lang.System.Logger.Level.*; + +import java.lang.System.Logger; +import java.time.ZonedDateTime; +import java.time.format.DateTimeParseException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.google.common.collect.Iterators; + +final class PListContentHandler extends DefaultHandler { + + private static final Logger LOGGER = System.getLogger(PListContentHandler.class.getName()); + + private static final class PListPathImpl implements PListPath { + final LinkedList keys = new LinkedList<>(); + final List keysDepths = new ArrayList<>(); + int depth = 0; + + void add(final String key) { + trim(); + keysDepths.add(depth); + keys.add(key); + } + + void trim() { + for (int i = keysDepths.size() - 1; i >= 0; i--) { + if (keysDepths.get(i) >= depth) { + keysDepths.remove(i); + keys.remove(i); + } + } + } + + @Override + public String get(final int index) { + return keys.get(index); + } + + @Override + public String first() { + return keys.getFirst(); + } + + @Override + public String last() { + return keys.getLast(); + } + + @Override + public Iterator iterator() { + return Iterators.unmodifiableIterator(keys.iterator()); + } + + @Override + public int size() { + return keys.size(); + } + + @Override + public String toString() { + return String.join("/", keys.toArray(String[]::new)); + } + } + + private final class PListObject { + + @Nullable + final PListObject parent; + final Object values; + + PListObject(@Nullable final PListObject parent, final Object values) { + this.parent = parent; + this.values = values; + } + + @SuppressWarnings("unchecked") + void addValue(final Object value) { + if (values instanceof PropertySettable) { + ((PropertySettable) values).setProperty(path.last(), value); + } else if (values instanceof List) { + ((List) values).add(value); + } + } + } + + @Nullable + private PListObject currObject; + + @Nullable + private T result; + + private final PropertySettable.Factory objectFactory; + private final PListPathImpl path = new PListPathImpl(); + + /** captures the text content of an XML node */ + private final StringBuilder text = new StringBuilder(); + + PListContentHandler(final PropertySettable.Factory objectFactory) { + this.objectFactory = objectFactory; + } + + @SuppressWarnings("unchecked") + @Override + public void startElement(@Nullable final String uri, @Nullable final String localName, @Nullable final String qName, + @Nullable final Attributes attributes) throws SAXException { + assert localName != null; + + path.depth++; + + switch (localName) { + case "dict": + if (result == null) { + result = (T) objectFactory.create(path); + currObject = new PListObject(currObject, result); + } else { + currObject = new PListObject(currObject, objectFactory.create(path)); + } + break; + case "array": + if (result == null) { + result = (T) new ArrayList<>(); + currObject = new PListObject(currObject, result); + } else { + currObject = new PListObject(currObject, new ArrayList<>()); + } + break; + } + + text.setLength(0); + } + + @Override + public void endElement(@Nullable final String uri, @Nullable final String localName, @Nullable final String qName) + throws SAXException { + assert localName != null; + + final var currObject = this.currObject; + if (currObject == null) { + throw new SAXException("Root or element not found!"); + } + + path.trim(); + path.depth--; + + switch (localName) { + case "key": + if (!(currObject.values instanceof PropertySettable)) { + LOGGER.log(WARNING, " tag can only be used inside an open element"); + break; + } + path.add(text.toString()); + break; + case "dict": + case "array": + final var parent = currObject.parent; + if (parent != null) { + parent.addValue(currObject.values); + this.currObject = parent; + } + break; + case "string": + case "data": + currObject.addValue(text.toString()); + break; + case "date": // e.g. 2007-10-25T12:36:35Z + try { + currObject.addValue(ZonedDateTime.parse(text.toString())); + } catch (final DateTimeParseException ex) { + LOGGER.log(WARNING, "Failed to parse date '" + text + "'. " + ex); + } + break; + case "integer": + try { + currObject.addValue(Integer.parseInt(text.toString())); + } catch (final NumberFormatException ex) { + LOGGER.log(WARNING, "Failed to parse integer '" + text + "'. " + ex); + } + break; + case "real": + try { + currObject.addValue(Float.parseFloat(text.toString())); + } catch (final NumberFormatException ex) { + LOGGER.log(WARNING, "Failed to parse real as float '" + text + "'. " + ex); + } + break; + case "true": + currObject.addValue(Boolean.TRUE); + break; + case "false": + currObject.addValue(Boolean.FALSE); + break; + case "plist": + break; + default: + LOGGER.log(WARNING, "Invalid tag name: " + localName); + } + } + + @Override + public void characters(final char @Nullable [] ch, final int start, final int length) throws SAXException { + text.append(ch, start, length); + } + + void characters(final String chars) { + text.append(chars); + } + + public T getResult() { + assert result != null; + return result; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListObject.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListObject.java deleted file mode 100644 index 8b21b83a2..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListObject.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.parser; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public abstract class PListObject { - - public final PListObject parent; - private final List arrayValues; - private final Map mapValues; - - private String lastKey; - - public PListObject(PListObject parent, boolean valueAsArray) { - this.parent = parent; - if (valueAsArray) { - this.arrayValues = new ArrayList<>(); - this.mapValues = null; - } else { - this.arrayValues = null; - this.mapValues = createRaw(); - } - } - - public String getLastKey() { - return lastKey; - } - - public void setLastKey(String lastKey) { - this.lastKey = lastKey; - } - - public void addValue(Object value) { - if (isValueAsArray()) { - arrayValues.add(value); - } else { - mapValues.put(getLastKey(), value); - } - } - - public boolean isValueAsArray() { - return arrayValues != null; - } - - public Object getValue() { - if (isValueAsArray()) { - return arrayValues; - } - return mapValues; - } - - protected abstract Map createRaw(); -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListParser.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListParser.java new file mode 100644 index 000000000..a8cb26e9b --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListParser.java @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2022 Sebastian Thomschke and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Sebastian Thomschke - initial implementation + */ +package org.eclipse.tm4e.core.internal.parser; + +import java.io.InputStream; + +public interface PListParser { + T parse(InputStream contents) throws Exception; +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListParserJSON.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListParserJSON.java new file mode 100644 index 000000000..b1e792483 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListParserJSON.java @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2015-2018 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.parser; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +import org.xml.sax.SAXException; + +import com.google.gson.stream.JsonReader; + +public final class PListParserJSON implements PListParser { + + private final PropertySettable.Factory objectFactory; + + public PListParserJSON(final PropertySettable.Factory objectFactory) { + this.objectFactory = objectFactory; + } + + @Override + public T parse(final InputStream contents) throws IOException, SAXException { + final var pList = new PListContentHandler(objectFactory); + try (final var reader = new JsonReader(new InputStreamReader(contents, StandardCharsets.UTF_8))) { + // reader.setLenient(true); + boolean parsing = true; + pList.startElement(null, "plist", null, null); + while (parsing) { + final var nextToken = reader.peek(); + switch (nextToken) { + case BEGIN_ARRAY: + pList.startElement(null, "array", null, null); + reader.beginArray(); + break; + case END_ARRAY: + pList.endElement(null, "array", null); + reader.endArray(); + break; + case BEGIN_OBJECT: + pList.startElement(null, "dict", null, null); + reader.beginObject(); + break; + case END_OBJECT: + pList.endElement(null, "dict", null); + reader.endObject(); + break; + case NAME: + pList.startElement(null, "key", null, null); + pList.characters(reader.nextName()); + pList.endElement(null, "key", null); + break; + case NULL: + reader.nextNull(); + break; + case BOOLEAN: + reader.nextBoolean(); + break; + case NUMBER: + reader.nextLong(); + break; + case STRING: + pList.startElement(null, "string", null, null); + pList.characters(reader.nextString()); + pList.endElement(null, "string", null); + break; + case END_DOCUMENT: + parsing = false; + break; + default: + break; + } + } + pList.endElement(null, "plist", null); + } + return pList.getResult(); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListParserXML.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListParserXML.java new file mode 100644 index 000000000..f001af3d4 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListParserXML.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.parser; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.xml.XMLConstants; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; + +public final class PListParserXML implements PListParser { + + private final PropertySettable.Factory objectFactory; + + public PListParserXML(final PropertySettable.Factory objectFactory) { + this.objectFactory = objectFactory; + } + + @Override + public T parse(final InputStream contents) throws IOException, ParserConfigurationException, SAXException { + final var spf = SAXParserFactory.newInstance(); + spf.setNamespaceAware(true); + + // make parser invulnerable to XXE attacks, see https://rules.sonarsource.com/java/RSPEC-2755 + spf.setFeature("http://xml.org/sax/features/external-general-entities", false); + spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + + final var saxParser = spf.newSAXParser(); + + // make parser invulnerable to XXE attacks, see https://rules.sonarsource.com/java/RSPEC-2755 + saxParser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + saxParser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + + final XMLReader xmlReader = saxParser.getXMLReader(); + xmlReader.setEntityResolver((publicId, systemId) -> new InputSource( + new ByteArrayInputStream("".getBytes()))); + final var result = new PListContentHandler(objectFactory); + xmlReader.setContentHandler(result); + xmlReader.parse(new InputSource(contents)); + return result.getResult(); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListParserYAML.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListParserYAML.java new file mode 100644 index 000000000..0d0ef99fc --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListParserYAML.java @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2022 Sebastian Thomschke and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Sebastian Thomschke - initial implementation + */ +package org.eclipse.tm4e.core.internal.parser; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import java.io.InputStream; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.xml.sax.SAXException; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.error.YAMLException; + +/** + * Parses TextMate Grammar file in YAML format. + */ +public final class PListParserYAML implements PListParser { + + private final PropertySettable.Factory objectFactory; + + public PListParserYAML(final PropertySettable.Factory objectFactory) { + this.objectFactory = objectFactory; + } + + @SuppressWarnings("unchecked") + private void addListToPList(final PListContentHandler pList, final List list) throws SAXException { + pList.startElement(null, "array", null, null); + + for (final Object item : list) { + if (item instanceof List) { + addListToPList(pList, (List) item); + } else if (item instanceof Map) { + addMapToPList(pList, (Map) item); + } else { + addStringToPList(pList, item.toString()); + } + } + + pList.endElement(null, "array", null); + } + + @SuppressWarnings("unchecked") + private void addMapToPList(final PListContentHandler pList, final Map map) + throws SAXException { + pList.startElement(null, "dict", null, null); + + for (final Entry entry : map.entrySet()) { + pList.startElement(null, "key", null, null); + pList.characters(entry.getKey()); + pList.endElement(null, "key", null); + if (entry.getValue() instanceof List) { + addListToPList(pList, (List) entry.getValue()); + } else if (entry.getValue() instanceof Map) { + addMapToPList(pList, (Map) entry.getValue()); + } else { + addStringToPList(pList, castNonNull(entry.getValue()).toString()); + } + } + + pList.endElement(null, "dict", null); + } + + private void addStringToPList(final PListContentHandler pList, final String value) throws SAXException { + pList.startElement(null, "string", null, null); + pList.characters(value); + pList.endElement(null, "string", null); + } + + @Override + public T parse(final InputStream contents) throws SAXException, YAMLException { + final var pList = new PListContentHandler(objectFactory); + pList.startElement(null, "plist", null, null); + addMapToPList(pList, new Yaml().loadAs(contents, Map.class)); + pList.endElement(null, "plist", null); + return pList.getResult(); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListPath.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListPath.java new file mode 100644 index 000000000..bdc82438f --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PListPath.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2022 Sebastian Thomschke and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Sebastian Thomschke - initial implementation + */ +package org.eclipse.tm4e.core.internal.parser; + +/** + * Represents the hierarchical path of an PList value calculated based on the <key> tags. E.g. + *
  • fileTypes + *
  • scopeName + *
  • repository/constants/patterns/patterns + *
  • repository/statements/patterns/include + *
  • repository/var-single-variable/beginCaptures + */ +public interface PListPath extends Iterable { + + String first(); + + String get(int index); + + String last(); + + int size(); +} \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PropertySettable.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PropertySettable.java new file mode 100644 index 000000000..20091d74d --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/PropertySettable.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2022 Sebastian Thomschke and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Sebastian Thomschke - initial implementation + */ +package org.eclipse.tm4e.core.internal.parser; + +public interface PropertySettable { + + public interface Factory { + PropertySettable create(I args); + } + + void setProperty(String name, V value); +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/json/JSONPListParser.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/json/JSONPListParser.java deleted file mode 100644 index 2885057eb..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/json/JSONPListParser.java +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright (c) 2015-2018 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.parser.json; - -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; - -import org.eclipse.tm4e.core.internal.parser.PList; - -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; - -public class JSONPListParser { - - private final boolean theme; - - public JSONPListParser(boolean theme) { - this.theme = theme; - } - - public T parse(InputStream contents) throws Exception { - PList pList = new PList(theme); - JsonReader reader = new JsonReader(new InputStreamReader(contents, StandardCharsets.UTF_8)); - // reader.setLenient(true); - boolean parsing = true; - while (parsing) { - JsonToken nextToken = reader.peek(); - switch (nextToken) { - case BEGIN_ARRAY: - pList.startElement(null, "array", null, null); - reader.beginArray(); - break; - case END_ARRAY: - pList.endElement(null, "array", null); - reader.endArray(); - break; - case BEGIN_OBJECT: - pList.startElement(null, "dict", null, null); - reader.beginObject(); - break; - case END_OBJECT: - pList.endElement(null, "dict", null); - reader.endObject(); - break; - case NAME: - String lastName = reader.nextName(); - pList.startElement(null, "key", null, null); - pList.characters(lastName.toCharArray(), 0, lastName.length()); - pList.endElement(null, "key", null); - break; - case NULL: - reader.nextNull(); - break; - case BOOLEAN: - reader.nextBoolean(); - break; - case NUMBER: - reader.nextLong(); - break; - case STRING: - String value = reader.nextString(); - pList.startElement(null, "string", null, null); - pList.characters(value.toCharArray(), 0, value.length()); - pList.endElement(null, "string", null); - break; - case END_DOCUMENT: - parsing = false; - break; - default: - break; - } - } - reader.close(); - return pList.getResult(); - } - -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/package-info.java new file mode 100644 index 000000000..ee4fdc13b --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.core.internal.parser; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/xml/XMLPListParser.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/xml/XMLPListParser.java deleted file mode 100644 index c54b9926b..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/parser/xml/XMLPListParser.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.parser.xml; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; - -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.eclipse.tm4e.core.internal.parser.PList; -import org.xml.sax.InputSource; -import org.xml.sax.XMLReader; - -public class XMLPListParser { - - private final boolean theme; - - public XMLPListParser(boolean theme) { - this.theme = theme; - } - - public T parse(InputStream contents) throws Exception { - SAXParserFactory spf = SAXParserFactory.newInstance(); - spf.setNamespaceAware(true); - SAXParser saxParser = spf.newSAXParser(); - XMLReader xmlReader = saxParser.getXMLReader(); - xmlReader.setEntityResolver((arg0, arg1) -> new InputSource(new ByteArrayInputStream("".getBytes()))); - PList result = new PList<>(theme); - xmlReader.setContentHandler(result); - xmlReader.parse(new InputSource(contents)); - return result.getResult(); - } -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/IGrammarRepository.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/registry/IGrammarRepository.java similarity index 61% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/IGrammarRepository.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/registry/IGrammarRepository.java index f13f298e6..e185e12ac 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/grammar/IGrammarRepository.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/registry/IGrammarRepository.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,19 +11,21 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java */ -package org.eclipse.tm4e.core.grammar; +package org.eclipse.tm4e.core.internal.registry; import java.util.Collection; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tm4e.core.internal.types.IRawGrammar; /** * TextMate grammar repository API. * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/grammar.ts + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/grammar.ts * */ public interface IGrammarRepository { @@ -31,10 +33,12 @@ public interface IGrammarRepository { /** * Lookup a raw grammar. */ + @Nullable IRawGrammar lookup(String scopeName); /** * Returns the injections for the given grammar */ + @Nullable Collection injections(String targetScope); } diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/registry/SyncRegistry.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/registry/SyncRegistry.java new file mode 100644 index 000000000..babb9978b --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/registry/SyncRegistry.java @@ -0,0 +1,209 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Initial code from https://github.com/Microsoft/vscode-textmate/ + * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. + * Initial license: MIT + * + * Contributors: + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.registry; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.grammar.IGrammar; +import org.eclipse.tm4e.core.internal.grammar.BalancedBracketSelectors; +import org.eclipse.tm4e.core.internal.grammar.Grammar; +import org.eclipse.tm4e.core.internal.grammar.RawRepository; +import org.eclipse.tm4e.core.internal.grammar.RawRule; +import org.eclipse.tm4e.core.internal.theme.IThemeProvider; +import org.eclipse.tm4e.core.internal.theme.Theme; +import org.eclipse.tm4e.core.internal.theme.ThemeTrieElementRule; +import org.eclipse.tm4e.core.internal.types.IRawGrammar; +import org.eclipse.tm4e.core.internal.types.IRawRepository; +import org.eclipse.tm4e.core.internal.types.IRawRule; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/registry.ts + */ +public final class SyncRegistry implements IGrammarRepository, IThemeProvider { + + private final Map grammars = new HashMap<>(); + private final Map<@Nullable String, IRawGrammar> rawGrammars = new HashMap<>(); + private final Map<@Nullable String, Collection> injectionGrammars = new HashMap<>(); + private Theme theme; + + public SyncRegistry(final Theme theme) { + this.theme = theme; + } + + public void setTheme(final Theme theme) { + this.theme = theme; + this.grammars.values().forEach(Grammar::onDidChangeTheme); + } + + public Set getColorMap() { + return this.theme.getColorMap(); + } + + /** + * Add `grammar` to registry and return a list of referenced scope names + * + * TODO implementation differs from upstream + */ + public Collection addGrammar(final IRawGrammar grammar, + @Nullable final Collection injectionScopeNames) { + this.rawGrammars.put(grammar.getScopeName(), grammar); + final Collection includedScopes = new ArrayList<>(); + collectIncludedScopes(includedScopes, grammar); + + if (injectionScopeNames != null) { + this.injectionGrammars.put(grammar.getScopeName(), injectionScopeNames); + injectionScopeNames.forEach(scopeName -> addIncludedScope(scopeName, includedScopes)); + } + return includedScopes; + } + + @Override + @Nullable + public IRawGrammar lookup(final String scopeName) { + return this.rawGrammars.get(scopeName); + } + + @Override + @Nullable + public Collection injections(final String targetScope) { + return this.injectionGrammars.get(targetScope); + } + + /** + * Get the default theme settings + */ + @Override + public ThemeTrieElementRule getDefaults() { + return this.theme.getDefaults(); + } + + /** + * Match a scope in the theme. + */ + @Override + public List themeMatch(final String scopeName) { + return this.theme.match(scopeName); + } + + /** + * Lookup a grammar. + */ + @Nullable + public IGrammar grammarForScopeName(final String scopeName, final int initialLanguage, + @Nullable final Map embeddedLanguages, + @Nullable final Map tokenTypes, + @Nullable final BalancedBracketSelectors balancedBracketSelectors) { + if (!this.grammars.containsKey(scopeName)) { + final var rawGrammar = lookup(scopeName); + if (rawGrammar == null) { + return null; + } + this.grammars.put(scopeName, + new Grammar(scopeName, rawGrammar, initialLanguage, embeddedLanguages, tokenTypes, + balancedBracketSelectors, this, this)); + } + return this.grammars.get(scopeName); + } + + private static void collectIncludedScopes(final Collection result, final IRawGrammar grammar) { + final var grammarPatterns = grammar.getPatterns(); + if (grammarPatterns != null) { + extractIncludedScopesInPatterns(result, grammarPatterns); + } + + if (grammar.isRepositorySet()) { + final IRawRepository repository = grammar.getRepository(); + extractIncludedScopesInRepository(result, repository); + } + + // remove references to own scope (avoid recursion) + result.remove(grammar.getScopeName()); + } + + /** + * Fill in `result` all external included scopes in `patterns` + */ + private static void extractIncludedScopesInPatterns(final Collection result, + final Collection patterns) { + for (final IRawRule pattern : patterns) { + final Collection p = pattern.getPatterns(); + if (p != null) { + extractIncludedScopesInPatterns(result, p); + } + + final String include = pattern.getInclude(); + if (include == null) { + continue; + } + + if (include.equals(RawRepository.DOLLAR_BASE) || include.equals(RawRepository.DOLLAR_SELF)) { + // Special includes that can be resolved locally in this grammar + continue; + } + + if (include.charAt(0) == '#') { + // Local include from this grammar + continue; + } + + final int sharpIndex = include.indexOf('#'); + if (sharpIndex >= 0) { + addIncludedScope(include.substring(0, sharpIndex), result); + } else { + addIncludedScope(include, result); + } + } + } + + private static void addIncludedScope(final String scopeName, final Collection includedScopes) { + if (!includedScopes.contains(scopeName)) { + includedScopes.add(scopeName); + } + } + + /** + * Fill in `result` all external included scopes in `repository` + */ + private static void extractIncludedScopesInRepository(final Collection result, + final IRawRepository repository) { + if (!(repository instanceof RawRule)) { + return; + } + final RawRule rawRepository = (RawRule) repository; + for (final var entry : rawRepository.values()) { + final IRawRule rule = (IRawRule) castNonNull(entry); + final var patterns = rule.getPatterns(); + if (patterns != null) { + extractIncludedScopesInPatterns(result, patterns); + } + final var repo = rule.getRepository(); + if (repo != null) { + extractIncludedScopesInRepository(result, repo); + } + } + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/registry/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/registry/package-info.java new file mode 100644 index 000000000..11cd82628 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/registry/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.core.internal.registry; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/BeginEndRule.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/BeginEndRule.java index 3f89bbed2..79525d380 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/BeginEndRule.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/BeginEndRule.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,83 +11,102 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.rule; - + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.rule; + import java.util.List; -import org.eclipse.tm4e.core.internal.oniguruma.IOnigCaptureIndex; - -public class BeginEndRule extends Rule { - - private RegExpSource begin; - public List beginCaptures; - private RegExpSource end; - public boolean endHasBackReferences; - public List endCaptures; - public boolean applyEndPatternLast; - public final boolean hasMissingPatterns; - public Integer[] patterns; - private RegExpSourceList cachedCompiledPatterns; - - public BeginEndRule(int id, String name, String contentName, String begin, List beginCaptures, - String end, List endCaptures, boolean applyEndPatternLast, ICompilePatternsResult patterns) { - super(id, name, contentName); - this.begin = new RegExpSource(begin, this.id); - this.beginCaptures = beginCaptures; - this.end = new RegExpSource(end, -1); - this.endHasBackReferences = this.end.hasBackReferences(); - this.endCaptures = endCaptures; - this.applyEndPatternLast = applyEndPatternLast; - this.patterns = patterns.patterns; - this.hasMissingPatterns = patterns.hasMissingPatterns; - this.cachedCompiledPatterns = null; - } - - public String getEndWithResolvedBackReferences(String lineText, IOnigCaptureIndex[] captureIndices) { - return this.end.resolveBackReferences(lineText, captureIndices); - } - +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.oniguruma.OnigCaptureIndex; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts + */ +public final class BeginEndRule extends Rule { + + private final RegExpSource begin; + public final List<@Nullable CaptureRule> beginCaptures; + + private final RegExpSource end; + public final List<@Nullable CaptureRule> endCaptures; + public final boolean endHasBackReferences; + private final boolean applyEndPatternLast; + + final boolean hasMissingPatterns; + final int[] patterns; + + @Nullable + private RegExpSourceList cachedCompiledPatterns; + + BeginEndRule(final int id, @Nullable final String name, @Nullable final String contentName, final String begin, + final List<@Nullable CaptureRule> beginCaptures, @Nullable final String end, final List<@Nullable CaptureRule> endCaptures, + final boolean applyEndPatternLast, + final CompilePatternsResult patterns) { + super(id, name, contentName); + this.begin = new RegExpSource(begin, this.id); + this.beginCaptures = beginCaptures; + this.end = new RegExpSource(end == null ? "\uFFFF" : end, -1); + this.endHasBackReferences = this.end.hasBackReferences; + this.endCaptures = endCaptures; + this.applyEndPatternLast = applyEndPatternLast; + this.patterns = patterns.patterns; + this.hasMissingPatterns = patterns.hasMissingPatterns; + } + + public String getEndWithResolvedBackReferences(final String lineText, final OnigCaptureIndex[] captureIndices) { + return this.end.resolveBackReferences(lineText, captureIndices); + } + + @Override + public void collectPatternsRecursive(final IRuleRegistry grammar, final RegExpSourceList out, + final boolean isFirst) { + if (isFirst) { + for (final int pattern : this.patterns) { + final Rule rule = grammar.getRule(pattern); + rule.collectPatternsRecursive(grammar, out, false); + } + } else { + out.add(this.begin); + } + } + @Override - public void collectPatternsRecursive(IRuleRegistry grammar, RegExpSourceList out, boolean isFirst) { - if (isFirst) { - for (Integer pattern : this.patterns) { - Rule rule = grammar.getRule(pattern); - rule.collectPatternsRecursive(grammar, out, false); - } - } else { - out.push(this.begin); - } - } - + public CompiledRule compile(final IRuleRegistry grammar, @Nullable final String endRegexSource) { + return getCachedCompiledPatterns(grammar, endRegexSource).compile(); + } + @Override - public ICompiledRule compile(IRuleRegistry grammar, String endRegexSource, boolean allowA, boolean allowG) { - RegExpSourceList precompiled = this.precompile(grammar); - if (this.end.hasBackReferences()) { - if (this.applyEndPatternLast) { - precompiled.setSource(precompiled.length() - 1, endRegexSource); - } else { - precompiled.setSource(0, endRegexSource); - } - } - return this.cachedCompiledPatterns.compile(grammar, allowA, allowG); - } - - private RegExpSourceList precompile(IRuleRegistry grammar) { - if (this.cachedCompiledPatterns == null) { - this.cachedCompiledPatterns = new RegExpSourceList(); - - this.collectPatternsRecursive(grammar, this.cachedCompiledPatterns, true); - - if (this.applyEndPatternLast) { - this.cachedCompiledPatterns.push(this.end.hasBackReferences() ? this.end.clone() : this.end); - } else { - this.cachedCompiledPatterns.unshift(this.end.hasBackReferences() ? this.end.clone() : this.end); - } - } - return this.cachedCompiledPatterns; - } - -} + public CompiledRule compileAG(final IRuleRegistry grammar, @Nullable final String endRegexSource, + final boolean allowA, final boolean allowG) { + return getCachedCompiledPatterns(grammar, endRegexSource).compileAG(allowA, allowG); + } + + private RegExpSourceList getCachedCompiledPatterns(final IRuleRegistry grammar, + @Nullable final String endRegexSource) { + var cachedCompiledPatterns = this.cachedCompiledPatterns; + if (cachedCompiledPatterns == null) { + cachedCompiledPatterns = new RegExpSourceList(); + + collectPatternsRecursive(grammar, cachedCompiledPatterns, true); + + if (this.applyEndPatternLast) { + cachedCompiledPatterns.add(this.endHasBackReferences ? this.end.clone() : this.end); + } else { + cachedCompiledPatterns.remove(this.endHasBackReferences ? this.end.clone() : this.end); + } + this.cachedCompiledPatterns = cachedCompiledPatterns; + } + if (this.endHasBackReferences && endRegexSource != null) { + if (this.applyEndPatternLast) { + cachedCompiledPatterns.setSource(cachedCompiledPatterns.length() - 1, endRegexSource); + } else { + cachedCompiledPatterns.setSource(0, endRegexSource); + } + } + return cachedCompiledPatterns; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/BeginWhileRule.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/BeginWhileRule.java index 7c34aa67f..e8948f8be 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/BeginWhileRule.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/BeginWhileRule.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,85 +11,106 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.rule; - + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.rule; + import java.util.List; -import org.eclipse.tm4e.core.internal.oniguruma.IOnigCaptureIndex; - -public class BeginWhileRule extends Rule { - - private RegExpSource begin; - public final List beginCaptures; - public final List whileCaptures; - private RegExpSource _while; - public final boolean whileHasBackReferences; - public final boolean hasMissingPatterns; - public final Integer[] patterns; - private RegExpSourceList cachedCompiledPatterns; - private RegExpSourceList cachedCompiledWhilePatterns; - - public BeginWhileRule(/* $location:ILocation, */ int id, String name, String contentName, String begin, - List beginCaptures, String _while, List whileCaptures, - ICompilePatternsResult patterns) { - super(/* $location, */id, name, contentName); - this.begin = new RegExpSource(begin, this.id); - this.beginCaptures = beginCaptures; - this.whileCaptures = whileCaptures; - this._while = new RegExpSource(_while, -2); - this.whileHasBackReferences = this._while.hasBackReferences(); - this.patterns = patterns.patterns; - this.hasMissingPatterns = patterns.hasMissingPatterns; - this.cachedCompiledPatterns = null; - this.cachedCompiledWhilePatterns = null; - } - - public String getWhileWithResolvedBackReferences(String lineText, IOnigCaptureIndex[] captureIndices) { - return this._while.resolveBackReferences(lineText, captureIndices); - } - +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.oniguruma.OnigCaptureIndex; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts + */ +public final class BeginWhileRule extends Rule { + + private final RegExpSource begin; + public final List<@Nullable CaptureRule> beginCaptures; + public final List<@Nullable CaptureRule> whileCaptures; + private final RegExpSource _while; + public final boolean whileHasBackReferences; + final boolean hasMissingPatterns; + final int[] patterns; + + @Nullable + private RegExpSourceList cachedCompiledPatterns; + + @Nullable + private RegExpSourceList cachedCompiledWhilePatterns; + + BeginWhileRule(final int id, @Nullable final String name, @Nullable final String contentName, final String begin, + final List<@Nullable CaptureRule> beginCaptures, final String _while, final List<@Nullable CaptureRule> whileCaptures, + final CompilePatternsResult patterns) { + super(/* $location, */id, name, contentName); + this.begin = new RegExpSource(begin, this.id); + this.beginCaptures = beginCaptures; + this.whileCaptures = whileCaptures; + this._while = new RegExpSource(_while, -2); + this.whileHasBackReferences = this._while.hasBackReferences; + this.patterns = patterns.patterns; + this.hasMissingPatterns = patterns.hasMissingPatterns; + } + + public String getWhileWithResolvedBackReferences(final String lineText, final OnigCaptureIndex[] captureIndices) { + return this._while.resolveBackReferences(lineText, captureIndices); + } + + @Override + public void collectPatternsRecursive(final IRuleRegistry grammar, final RegExpSourceList out, final boolean isFirst) { + if (isFirst) { + Rule rule; + for (final int pattern : patterns) { + rule = grammar.getRule(pattern); + rule.collectPatternsRecursive(grammar, out, false); + } + } else { + out.add(this.begin); + } + } + @Override - public void collectPatternsRecursive(IRuleRegistry grammar, RegExpSourceList out, boolean isFirst) { - if (isFirst) { - Rule rule; - for (Integer pattern : patterns) { - rule = grammar.getRule(pattern); - rule.collectPatternsRecursive(grammar, out, false); - } - } else { - out.push(this.begin); - } - } - + public CompiledRule compile(final IRuleRegistry grammar, @Nullable final String endRegexSource) { + return getCachedCompiledPatterns(grammar).compile(); + } + @Override - public ICompiledRule compile(IRuleRegistry grammar, String endRegexSource, boolean allowA, boolean allowG) { - this.precompile(grammar); - return this.cachedCompiledPatterns.compile(grammar, allowA, allowG); - } - - private void precompile(IRuleRegistry grammar) { - if (this.cachedCompiledPatterns == null) { - this.cachedCompiledPatterns = new RegExpSourceList(); - this.collectPatternsRecursive(grammar, this.cachedCompiledPatterns, true); - } - } - - public ICompiledRule compileWhile(IRuleRegistry grammar, String endRegexSource, boolean allowA, boolean allowG) { - this.precompileWhile(); - if (this._while.hasBackReferences()) { - this.cachedCompiledWhilePatterns.setSource(0, endRegexSource); - } - return this.cachedCompiledWhilePatterns.compile(grammar, allowA, allowG); - } - - private void precompileWhile() { - if (this.cachedCompiledWhilePatterns == null) { - this.cachedCompiledWhilePatterns = new RegExpSourceList(); - this.cachedCompiledWhilePatterns.push(this._while.hasBackReferences() ? this._while.clone() : this._while); - } - } - -} + public CompiledRule compileAG(final IRuleRegistry grammar, @Nullable final String endRegexSource, final boolean allowA, + final boolean allowG) { + return getCachedCompiledPatterns(grammar).compileAG(allowA, allowG); + } + + private RegExpSourceList getCachedCompiledPatterns(final IRuleRegistry grammar) { + var cachedCompiledPatterns = this.cachedCompiledPatterns; + if (cachedCompiledPatterns == null) { + cachedCompiledPatterns = new RegExpSourceList(); + collectPatternsRecursive(grammar, cachedCompiledPatterns, true); + this.cachedCompiledPatterns = cachedCompiledPatterns; + } + return cachedCompiledPatterns; + } + + public CompiledRule compileWhile(@Nullable final String endRegexSource) { + return getCachedCompiledWhilePatterns(endRegexSource).compile(); + } + + public CompiledRule compileWhileAG(@Nullable final String endRegexSource, final boolean allowA, final boolean allowG) { + return getCachedCompiledWhilePatterns(endRegexSource).compileAG(allowA, allowG); + } + + private RegExpSourceList getCachedCompiledWhilePatterns(@Nullable final String endRegexSource) { + var cachedCompiledWhilePatterns = this.cachedCompiledWhilePatterns; + if (cachedCompiledWhilePatterns == null) { + cachedCompiledWhilePatterns = new RegExpSourceList(); + cachedCompiledWhilePatterns.add(this.whileHasBackReferences ? this._while.clone() : this._while); + if (whileHasBackReferences) { + cachedCompiledWhilePatterns.setSource(0, endRegexSource != null ? endRegexSource : "\uFFFF"); + } + this.cachedCompiledWhilePatterns = cachedCompiledWhilePatterns; + } + return cachedCompiledWhilePatterns; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/CaptureRule.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/CaptureRule.java index 6ab5aed9b..991bea032 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/CaptureRule.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/CaptureRule.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,26 +11,42 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.rule; - -public class CaptureRule extends Rule { - - public final Integer retokenizeCapturedWithRuleId; - - public CaptureRule(int id, String name, String contentName, Integer retokenizeCapturedWithRuleId) { - super(id, name, contentName); - this.retokenizeCapturedWithRuleId = retokenizeCapturedWithRuleId; + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.rule; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts + */ +public final class CaptureRule extends Rule { + + @Nullable + public final Integer retokenizeCapturedWithRuleId; + + CaptureRule(final int id, @Nullable final String name, @Nullable final String contentName, + @Nullable final Integer retokenizeCapturedWithRuleId) { + super(id, name, contentName); + this.retokenizeCapturedWithRuleId = retokenizeCapturedWithRuleId; } - @Override public void collectPatternsRecursive(IRuleRegistry grammar, RegExpSourceList out, boolean isFirst) { + @Override + public void collectPatternsRecursive(final IRuleRegistry grammar, final RegExpSourceList out, final boolean isFirst) { throw new UnsupportedOperationException(); } - @Override public ICompiledRule compile(IRuleRegistry grammar, String endRegexSource, boolean allowA, boolean allowG) { + @Override + public CompiledRule compile(final IRuleRegistry grammar, @Nullable final String endRegexSource) { throw new UnsupportedOperationException(); - } - -} + } + + @Override + public CompiledRule compileAG(final IRuleRegistry grammar, @Nullable final String endRegexSource, final boolean allowA, + final boolean allowG) { + throw new UnsupportedOperationException(); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/ICompilePatternsResult.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/CompilePatternsResult.java similarity index 63% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/ICompilePatternsResult.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/CompilePatternsResult.java index 3917a3c7b..582122ab8 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/ICompilePatternsResult.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/CompilePatternsResult.java @@ -13,19 +13,22 @@ * Contributors: * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.rule; - -import java.util.Collection; - -public class ICompilePatternsResult { + */ +package org.eclipse.tm4e.core.internal.rule; - public final Integer[] patterns; - public final boolean hasMissingPatterns; - - public ICompilePatternsResult(Collection patterns, boolean hasMissingPatterns) { - this.hasMissingPatterns = hasMissingPatterns; - this.patterns = patterns.toArray(new Integer[patterns.size()]); - } - -} +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts + */ +final class CompilePatternsResult { + + final int[] patterns; + final boolean hasMissingPatterns; + + CompilePatternsResult(final int[] patterns, final boolean hasMissingPatterns) { + this.hasMissingPatterns = hasMissingPatterns; + this.patterns = patterns; + } + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/CompiledRule.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/CompiledRule.java new file mode 100644 index 000000000..32d94b68a --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/CompiledRule.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Initial code from https://github.com/Microsoft/vscode-textmate/ + * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. + * Initial license: MIT + * + * Contributors: + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.rule; + +import java.util.List; + +import org.eclipse.tm4e.core.internal.oniguruma.OnigScanner; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts + */ +public final class CompiledRule { + + public final List debugRegExps; + public final OnigScanner scanner; + public final int[] rules; + + CompiledRule(final List regExps, final int[] rules) { + this.debugRegExps = regExps; + this.rules = rules; + this.scanner = new OnigScanner(regExps); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/ICompiledRule.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/ICompiledRule.java deleted file mode 100644 index b0fe90472..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/ICompiledRule.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/Microsoft/vscode-textmate/ - * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. - * Initial license: MIT - * - * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.rule; - -import org.eclipse.tm4e.core.internal.oniguruma.OnigScanner; - -public class ICompiledRule { - - public final OnigScanner scanner; - public final Integer[] rules; - - public ICompiledRule(OnigScanner scanner, Integer[] rules) { - this.scanner = scanner; - this.rules = rules; - } -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IGrammarRegistry.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IGrammarRegistry.java index edcdd10a5..e061935e5 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IGrammarRegistry.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IGrammarRegistry.java @@ -13,13 +13,20 @@ * Contributors: * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.rule; - -import org.eclipse.tm4e.core.internal.types.IRawGrammar; -import org.eclipse.tm4e.core.internal.types.IRawRepository; - -public interface IGrammarRegistry { - - IRawGrammar getExternalGrammar(String scopeName, IRawRepository repository); -} + */ +package org.eclipse.tm4e.core.internal.rule; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.types.IRawGrammar; +import org.eclipse.tm4e.core.internal.types.IRawRepository; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts + */ +interface IGrammarRegistry { + + @Nullable + IRawGrammar getExternalGrammar(String scopeName, IRawRepository repository); +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IRegExpSourceAnchorCache.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IRegExpSourceAnchorCache.java deleted file mode 100644 index 89a6e3724..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IRegExpSourceAnchorCache.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/Microsoft/vscode-textmate/ - * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. - * Initial license: MIT - * - * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.rule; - -public class IRegExpSourceAnchorCache { - - public final String A0_G0; - public final String A0_G1; - public final String A1_G0; - public final String A1_G1; - - public IRegExpSourceAnchorCache(String A0_G0, String A0_G1, String A1_G0, String A1_G1) { - this.A0_G0 = A0_G0; - this.A0_G1 = A0_G1; - this.A1_G0 = A1_G0; - this.A1_G1 = A1_G1; - } -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IRuleFactoryHelper.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IRuleFactoryHelper.java index 0a65f6750..f84c4195a 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IRuleFactoryHelper.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IRuleFactoryHelper.java @@ -13,9 +13,14 @@ * Contributors: * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.rule; - -public interface IRuleFactoryHelper extends IRuleRegistry, IGrammarRegistry { - -} + */ +package org.eclipse.tm4e.core.internal.rule; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts + */ +public interface IRuleFactoryHelper extends IRuleRegistry, IGrammarRegistry { + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IRuleRegistry.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IRuleRegistry.java index 3a8470487..c89bed843 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IRuleRegistry.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IRuleRegistry.java @@ -13,15 +13,22 @@ * Contributors: * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ + */ package org.eclipse.tm4e.core.internal.rule; import java.util.function.IntFunction; -public interface IRuleRegistry { - - Rule getRule(int patternId); - - Rule registerRule(IntFunction factory); - -} +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts + */ +public interface IRuleRegistry { + + /** + * @throws IndexOutOfBoundsException if no rule with the given id was found. + */ + Rule getRule(int patternId); + + T registerRule(IntFunction factory); +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IncludeOnlyRule.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IncludeOnlyRule.java index 42a036250..5e4b57a65 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IncludeOnlyRule.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/IncludeOnlyRule.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,39 +11,60 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.rule; - -public class IncludeOnlyRule extends Rule { - - public final boolean hasMissingPatterns; - public final Integer[] patterns; - private RegExpSourceList cachedCompiledPatterns; - - public IncludeOnlyRule(int id, String name, String contentName, ICompilePatternsResult patterns) { - super(id, name, contentName); - this.patterns = patterns.patterns; - this.hasMissingPatterns = patterns.hasMissingPatterns; - this.cachedCompiledPatterns = null; - } - + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.rule; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts + */ +final class IncludeOnlyRule extends Rule { + + final boolean hasMissingPatterns; + final int[] patterns; + + @Nullable + private RegExpSourceList cachedCompiledPatterns; + + IncludeOnlyRule(final int id, @Nullable final String name, @Nullable final String contentName, + final CompilePatternsResult patterns) { + super(id, name, contentName); + this.patterns = patterns.patterns; + this.hasMissingPatterns = patterns.hasMissingPatterns; + } + + @Override + public void collectPatternsRecursive(final IRuleRegistry grammar, final RegExpSourceList out, + final boolean isFirst) { + for (final int pattern : this.patterns) { + final Rule rule = grammar.getRule(pattern); + rule.collectPatternsRecursive(grammar, out, false); + } + } + @Override - public void collectPatternsRecursive(IRuleRegistry grammar, RegExpSourceList out, boolean isFirst) { - for (Integer pattern : this.patterns) { - Rule rule = grammar.getRule(pattern); - rule.collectPatternsRecursive(grammar, out, false); - } - } - + public CompiledRule compile(final IRuleRegistry grammar, @Nullable final String endRegexSource) { + return getCachedCompiledPatterns(grammar).compile(); + } + @Override - public ICompiledRule compile(IRuleRegistry grammar, String endRegexSource, boolean allowA, boolean allowG) { - if (this.cachedCompiledPatterns == null) { - this.cachedCompiledPatterns = new RegExpSourceList(); - this.collectPatternsRecursive(grammar, this.cachedCompiledPatterns, true); - } - return this.cachedCompiledPatterns.compile(grammar, allowA, allowG); - } - -} + public CompiledRule compileAG(final IRuleRegistry grammar, @Nullable final String endRegexSource, final boolean allowA, + final boolean allowG) { + return getCachedCompiledPatterns(grammar).compileAG(allowA, allowG); + } + + private RegExpSourceList getCachedCompiledPatterns(final IRuleRegistry grammar) { + var cachedCompiledPatterns = this.cachedCompiledPatterns; + if (cachedCompiledPatterns == null) { + cachedCompiledPatterns = new RegExpSourceList(); + this.collectPatternsRecursive(grammar, cachedCompiledPatterns, true); + this.cachedCompiledPatterns = cachedCompiledPatterns; + } + return cachedCompiledPatterns; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/MatchRule.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/MatchRule.java index dd6e01713..3d71100f1 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/MatchRule.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/MatchRule.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,37 +11,58 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.rule; - -import java.util.List; - -public class MatchRule extends Rule { - - private RegExpSource match; - public final List captures; - private RegExpSourceList cachedCompiledPatterns; - - public MatchRule(int id, String name, String match, List captures) { - super(id, name, null); - this.match = new RegExpSource(match, this.id); - this.captures = captures; - this.cachedCompiledPatterns = null; - } - + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.rule; + +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts + */ +public final class MatchRule extends Rule { + + private final RegExpSource match; + public final List<@Nullable CaptureRule> captures; + + @Nullable + private RegExpSourceList cachedCompiledPatterns; + + MatchRule(final int id, @Nullable final String name, final String match, final List<@Nullable CaptureRule> captures) { + super(id, name, null); + this.match = new RegExpSource(match, this.id); + this.captures = captures; + } + + @Override + public void collectPatternsRecursive(final IRuleRegistry grammar, final RegExpSourceList out, + final boolean isFirst) { + out.add(this.match); + } + @Override - public void collectPatternsRecursive(IRuleRegistry grammar, RegExpSourceList out, boolean isFirst) { - out.push(this.match); - } - + public CompiledRule compile(final IRuleRegistry grammar, @Nullable final String endRegexSource) { + return getCachedCompiledPatterns(grammar).compile(); + } + @Override - public ICompiledRule compile(IRuleRegistry grammar, String endRegexSource, boolean allowA, boolean allowG) { - if (this.cachedCompiledPatterns == null) { - this.cachedCompiledPatterns = new RegExpSourceList(); - this.collectPatternsRecursive(grammar, this.cachedCompiledPatterns, true); - } - return this.cachedCompiledPatterns.compile(grammar, allowA, allowG); - } -} + public CompiledRule compileAG(final IRuleRegistry grammar, @Nullable final String endRegexSource, final boolean allowA, + final boolean allowG) { + return getCachedCompiledPatterns(grammar).compileAG(allowA, allowG); + } + + private RegExpSourceList getCachedCompiledPatterns(final IRuleRegistry grammar) { + var cachedCompiledPatterns = this.cachedCompiledPatterns; + if (cachedCompiledPatterns == null) { + cachedCompiledPatterns = new RegExpSourceList(); + this.collectPatternsRecursive(grammar, cachedCompiledPatterns, true); + this.cachedCompiledPatterns = cachedCompiledPatterns; + } + return cachedCompiledPatterns; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/RegExpSource.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/RegExpSource.java index d0692b2c9..0d1bbc3a4 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/RegExpSource.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/RegExpSource.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,239 +11,179 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.rule; - -import java.util.Arrays; -import java.util.List; + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.rule; + +import java.util.ArrayList; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import org.eclipse.tm4e.core.internal.oniguruma.IOnigCaptureIndex; - -/** - * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts - * - */ -public class RegExpSource { - - private static final Pattern HAS_BACK_REFERENCES = Pattern.compile("\\\\(\\d+)"); - private static final Pattern BACK_REFERENCING_END = Pattern.compile("\\\\(\\d+)"); - private static final Pattern REGEXP_CHARACTERS = Pattern - .compile("[\\-\\\\\\{\\}\\*\\+\\?\\|\\^\\$\\.\\,\\[\\]\\(\\)\\#\\s]"); - - private int ruleId; - private boolean _hasAnchor; - private boolean _hasBackReferences; - private IRegExpSourceAnchorCache anchorCache; - private String source; - - public RegExpSource(String regExpSource, int ruleId) { - this(regExpSource, ruleId, true); - } - - public RegExpSource(String regExpSource, int ruleId, boolean handleAnchors) { - if (handleAnchors) { - this._handleAnchors(regExpSource); - } else { - this.source = regExpSource; - this._hasAnchor = false; - } - - if (this._hasAnchor) { - this.anchorCache = this._buildAnchorCache(); - } - - this.ruleId = ruleId; - this._hasBackReferences = HAS_BACK_REFERENCES.matcher(this.source).find(); - - // console.log('input: ' + regExpSource + ' => ' + this.source + ', ' + - // this.hasAnchor); - } - + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.oniguruma.OnigCaptureIndex; +import org.eclipse.tm4e.core.internal.utils.RegexSource; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts + */ +final class RegExpSource { + + private static final Pattern HAS_BACK_REFERENCES = Pattern.compile("\\\\(\\d+)"); + private static final Pattern BACK_REFERENCING_END = Pattern.compile("\\\\(\\d+)"); + + private String source; + final int ruleId; + final boolean hasBackReferences; + + private String @Nullable [][] anchorCache; + + RegExpSource(final String regExpSource, final int ruleId) { + this(regExpSource, ruleId, true); + } + + RegExpSource(final String regExpSource, final int ruleId, final boolean handleAnchors) { + if (handleAnchors && !regExpSource.isEmpty()) { + final int len = regExpSource.length(); + int lastPushedPos = 0; + final var output = new StringBuilder(); + + boolean hasAnchors = false; + for (int pos = 0; pos < len; pos++) { + final char ch = regExpSource.charAt(pos); + + if (ch == '\\') { + if (pos + 1 < len) { + final char nextCh = regExpSource.charAt(pos + 1); + if (nextCh == 'z') { + output.append(regExpSource.substring(lastPushedPos, pos)); + output.append("$(?!\\n)(? capturedValues = Arrays.stream(captureIndices) - .map(capture -> lineText.substring(capture.getStart(), capture.getEnd())).collect(Collectors.toList()); - Matcher m = BACK_REFERENCING_END.matcher(this.source); - StringBuffer sb = new StringBuffer(); - while (m.find()) { - String g1 = m.group(); - int index = Integer.parseInt(g1.substring(1, g1.length())); - String replacement = escapeRegExpCharacters(capturedValues.size() > index ? capturedValues.get(index) : ""); - m.appendReplacement(sb, replacement); - } - m.appendTail(sb); - return sb.toString(); - } - catch(Throwable e) { - //e.printStackTrace(); - } - - return lineText; - } - - private String escapeRegExpCharacters(String value) { - Matcher m = REGEXP_CHARACTERS.matcher(value); - StringBuffer sb = new StringBuffer(); - while (m.find()) { - m.appendReplacement(sb, "\\\\\\\\" + m.group()); - } - m.appendTail(sb); - return sb.toString(); - } - - private IRegExpSourceAnchorCache _buildAnchorCache() { - - // Collection A0_G0_result=new ArrayList(); - // Collection A0_G1_result=new ArrayList(); - // Collection A1_G0_result=new ArrayList(); - // Collection A1_G1_result=new ArrayList(); - - StringBuilder A0_G0_result = new StringBuilder(); - StringBuilder A0_G1_result = new StringBuilder(); - StringBuilder A1_G0_result = new StringBuilder(); - StringBuilder A1_G1_result = new StringBuilder(); - int pos; - int len; - char ch; - char nextCh; - - for (pos = 0, len = this.source.length(); pos < len; pos++) { - ch = this.source.charAt(pos); - A0_G0_result.append(ch); - A0_G1_result.append(ch); - A1_G0_result.append(ch); - A1_G1_result.append(ch); - - if (ch == '\\') { - if (pos + 1 < len) { - nextCh = this.source.charAt(pos + 1); - if (nextCh == 'A') { - A0_G0_result.append('\uFFFF'); - A0_G1_result.append('\uFFFF'); - A1_G0_result.append('A'); - A1_G1_result.append('A'); - } else if (nextCh == 'G') { - A0_G0_result.append('\uFFFF'); - A0_G1_result.append('G'); - A1_G0_result.append('\uFFFF'); - A1_G1_result.append('G'); - } else { - A0_G0_result.append(nextCh); - A0_G1_result.append(nextCh); - A1_G0_result.append(nextCh); - A1_G1_result.append(nextCh); - } - pos++; - } - } - } - - return new IRegExpSourceAnchorCache(A0_G0_result.toString(), A0_G1_result.toString(), A1_G0_result.toString(), - A1_G1_result.toString() - // StringUtils.join(A0_G0_result, ""), - // StringUtils.join(A0_G1_result, ""), - // StringUtils.join(A1_G0_result, ""), - // StringUtils.join(A1_G1_result, "") - ); - } - - public String resolveAnchors(boolean allowA, boolean allowG) { - if (!this._hasAnchor) { - return this.source; - } - - if (allowA) { - if (allowG) { - return this.anchorCache.A1_G1; - } else { - return this.anchorCache.A1_G0; - } - } else { - if (allowG) { - return this.anchorCache.A0_G1; - } else { - return this.anchorCache.A0_G0; - } - } + protected RegExpSource clone() { + return new RegExpSource(source, this.ruleId); } - public boolean hasAnchor() { - return this._hasAnchor; + void setSource(final String newSource) { + if (Objects.equals(source, newSource)) { + return; + } + this.source = newSource; + + if (hasAnchor()) { + this.anchorCache = buildAnchorCache(); + } } - public String getSource() { - return this.source; + @SuppressWarnings("null") + String resolveBackReferences(final String lineText, final OnigCaptureIndex[] captureIndices) { + final var capturedValues = new ArrayList(captureIndices.length); + for (final var capture : captureIndices) { + capturedValues.add(lineText.substring(capture.start, capture.end)); + } + return BACK_REFERENCING_END.matcher(this.source).replaceAll(match -> { + try { + final int index = Integer.parseInt(match.group(1)); + if (index < captureIndices.length) { + final var replacement = RegexSource.escapeRegExpCharacters(capturedValues.get(index)); + return Matcher.quoteReplacement(replacement); // see https://stackoverflow.com/a/70785772/5116073 + } + } catch (final NumberFormatException ex) { + // ignore + } + return ""; + }); + } + + private String[][] buildAnchorCache() { + final var source = this.source; + final var sourceLen = source.length(); + + final var A0_G0_result = new StringBuilder(sourceLen); + final var A0_G1_result = new StringBuilder(sourceLen); + final var A1_G0_result = new StringBuilder(sourceLen); + final var A1_G1_result = new StringBuilder(sourceLen); + + for (int pos = 0, len = sourceLen; pos < len; pos++) { + final char ch = source.charAt(pos); + A0_G0_result.append(ch); + A0_G1_result.append(ch); + A1_G0_result.append(ch); + A1_G1_result.append(ch); + + if (ch == '\\') { + if (pos + 1 < len) { + final char nextCh = source.charAt(pos + 1); + if (nextCh == 'A') { + A0_G0_result.append('\uFFFF'); + A0_G1_result.append('\uFFFF'); + A1_G0_result.append('A'); + A1_G1_result.append('A'); + } else if (nextCh == 'G') { + A0_G0_result.append('\uFFFF'); + A0_G1_result.append('G'); + A1_G0_result.append('\uFFFF'); + A1_G1_result.append('G'); + } else { + A0_G0_result.append(nextCh); + A0_G1_result.append(nextCh); + A1_G0_result.append(nextCh); + A1_G1_result.append(nextCh); + } + pos++; + } + } + } + + return new String[][] { + { A0_G0_result.toString(), A0_G1_result.toString() }, + { A1_G0_result.toString(), A1_G1_result.toString() } + }; } - public Integer getRuleId() { - return this.ruleId; + String resolveAnchors(final boolean allowA, final boolean allowG) { + final var anchorCache = this.anchorCache; + if (anchorCache == null) { + return this.source; + } + + return anchorCache[allowA ? 1 : 0][allowG ? 1 : 0]; } - public boolean hasBackReferences() { - return this._hasBackReferences; - } - -} + boolean hasAnchor() { + return anchorCache != null; + } + + String getSource() { + return this.source; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/RegExpSourceList.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/RegExpSourceList.java index b3c53d1c5..5e6d71733 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/RegExpSourceList.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/RegExpSourceList.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,134 +11,101 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.rule; - + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.rule; + import java.util.ArrayList; -import java.util.Collection; import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts + */ +final class RegExpSourceList { + + private final List items = new ArrayList<>(); + private boolean hasAnchors; + + @Nullable + private CompiledRule cached; + private final CompiledRule[][] anchorCache = new CompiledRule[2][2]; + + private void disposeCache() { + cached = null; + anchorCache[0][0] = null; + anchorCache[0][1] = null; + anchorCache[1][0] = null; + anchorCache[1][1] = null; + } + + void add(final RegExpSource item) { + items.add(item); + if (!hasAnchors) { + hasAnchors = item.hasAnchor(); + } + } + + void remove(final RegExpSource item) { + items.add(0, item); + if (!hasAnchors) { + hasAnchors = item.hasAnchor(); + } + } + + int length() { + return items.size(); + } + + void setSource(final int index, final String newSource) { + final RegExpSource r = items.get(index); + if (!Objects.equals(r.getSource(), newSource)) { + disposeCache(); + r.setSource(newSource); + } + } + + CompiledRule compile() { + var cached = this.cached; + if (cached == null) { + final List regexps = items.stream().map(RegExpSource::getSource).collect(Collectors.toList()); + cached = this.cached = new CompiledRule(regexps, getRules()); + } + return cached; + } + + CompiledRule compileAG(final boolean allowA, final boolean allowG) { + if (!hasAnchors) { + return compile(); + } + + final var indexA = allowA ? 1 : 0; + final var indexG = allowG ? 1 : 0; + + var rule = anchorCache[indexA][indexG]; + if (rule == null) { + rule = anchorCache[indexA][indexG] = resolveAnchors(allowA, allowG); + } + return rule; + } + + private CompiledRule resolveAnchors(final boolean allowA, final boolean allowG) { + final List regexps = items.stream().map(e -> e.resolveAnchors(allowA, allowG)) + .collect(Collectors.toList()); + return new CompiledRule(regexps, getRules()); + } -import org.eclipse.tm4e.core.internal.oniguruma.OnigScanner; - -/** - * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts - * - */ -public class RegExpSourceList { - - private class RegExpSourceListAnchorCache { - - public ICompiledRule A0_G0; - public ICompiledRule A0_G1; - public ICompiledRule A1_G0; - public ICompiledRule A1_G1; - - } - - private List _items; - private boolean _hasAnchors; - private ICompiledRule _cached; - private final RegExpSourceListAnchorCache _anchorCache; - - public RegExpSourceList() { - this._items = new ArrayList(); - this._hasAnchors = false; - this._cached = null; - this._anchorCache = new RegExpSourceListAnchorCache(); - } - - public void push(RegExpSource item) { - this._items.add(item); - this._hasAnchors = this._hasAnchors ? this._hasAnchors : item.hasAnchor(); - } - - public void unshift(RegExpSource item) { - this._items.add(0, item); - this._hasAnchors = this._hasAnchors ? this._hasAnchors : item.hasAnchor(); - } - - public int length() { - return this._items.size(); - } - - public void setSource(int index, String newSource) { - RegExpSource r = this._items.get(index); - if (!r.getSource().equals(newSource)) { - // bust the cache - this._cached = null; - this._anchorCache.A0_G0 = null; - this._anchorCache.A0_G1 = null; - this._anchorCache.A1_G0 = null; - this._anchorCache.A1_G1 = null; - r.setSource(newSource); - } - } - - public ICompiledRule compile(IRuleRegistry grammar, boolean allowA, boolean allowG) { - if (!this._hasAnchors) { - if (this._cached == null) { - List regexps = new ArrayList(); - for (RegExpSource regExpSource : _items) { - regexps.add(regExpSource.getSource()); - } - this._cached = new ICompiledRule(createOnigScanner(regexps.toArray(new String[0])), getRules()); - } - return this._cached; - } else { - if (this._anchorCache.A0_G0 == null) { - this._anchorCache.A0_G0 = (allowA == false && allowG == false) ? this._resolveAnchors(allowA, allowG) - : null; - } - if (this._anchorCache.A0_G1 == null) { - this._anchorCache.A0_G1 = (allowA == false && allowG == true) ? this._resolveAnchors(allowA, allowG) - : null; - } - if (this._anchorCache.A1_G0 == null) { - this._anchorCache.A1_G0 = (allowA == true && allowG == false) ? this._resolveAnchors(allowA, allowG) - : null; - } - if (this._anchorCache.A1_G1 == null) { - this._anchorCache.A1_G1 = (allowA == true && allowG == true) ? this._resolveAnchors(allowA, allowG) - : null; - } - if (allowA) { - if (allowG) { - return this._anchorCache.A1_G1; - } else { - return this._anchorCache.A1_G0; - } - } else { - if (allowG) { - return this._anchorCache.A0_G1; - } else { - return this._anchorCache.A0_G0; - } - } - } - - } - - private ICompiledRule _resolveAnchors(boolean allowA, boolean allowG) { - List regexps = new ArrayList(); - for (RegExpSource regExpSource : _items) { - regexps.add(regExpSource.resolveAnchors(allowA, allowG)); - } - return new ICompiledRule(createOnigScanner(regexps.toArray(new String[0])), getRules()); - } - - private OnigScanner createOnigScanner(String[] regexps) { - return new OnigScanner(regexps); - } - - private Integer[] getRules() { - Collection ruleIds = new ArrayList(); - for (RegExpSource item : this._items) { - ruleIds.add(item.getRuleId()); - } - return ruleIds.toArray(new Integer[0]); - } - -} + private int[] getRules() { + final var ruleIds = new int[items.size()]; + for (int i = 0; i < ruleIds.length; i++) { + ruleIds[i] = items.get(i).ruleId; + } + return ruleIds; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/Rule.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/Rule.java index e7d2544a0..ede8f48a2 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/Rule.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/Rule.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,48 +11,63 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.rule; - -import org.eclipse.tm4e.core.internal.oniguruma.IOnigCaptureIndex; -import org.eclipse.tm4e.core.internal.utils.RegexSource; - -public abstract class Rule { - - public final int id; - - private boolean nameIsCapturing; - private String name; - - private boolean contentNameIsCapturing; - private String contentName; - - public Rule(int id, String name, String contentName) { - this.id = id; - this.name = name; - this.nameIsCapturing = RegexSource.hasCaptures(this.name); - this.contentName = contentName; - this.contentNameIsCapturing = RegexSource.hasCaptures(this.contentName); - } - - public String getName(String lineText, IOnigCaptureIndex[] captureIndices) { - if (!this.nameIsCapturing) { - return this.name; - } - return RegexSource.replaceCaptures(this.name, lineText, captureIndices); - } - - public String getContentName(String lineText, IOnigCaptureIndex[] captureIndices) { - if (!this.contentNameIsCapturing) { - return this.contentName; - } - return RegexSource.replaceCaptures(this.contentName, lineText, captureIndices); - } - - public abstract void collectPatternsRecursive(IRuleRegistry grammar, RegExpSourceList out, boolean isFirst); - - public abstract ICompiledRule compile(IRuleRegistry grammar, String endRegexSource, boolean allowA, boolean allowG); - + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.rule; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.oniguruma.OnigCaptureIndex; +import org.eclipse.tm4e.core.internal.utils.RegexSource; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts + */ +public abstract class Rule { + + final int id; + + @Nullable + private final String name; + private final boolean nameIsCapturing; + + @Nullable + private final String contentName; + private final boolean contentNameIsCapturing; + + Rule(final int id, @Nullable final String name, final @Nullable String contentName) { + this.id = id; + this.name = name; + this.nameIsCapturing = RegexSource.hasCaptures(name); + this.contentName = contentName; + this.contentNameIsCapturing = RegexSource.hasCaptures(contentName); + } + + @Nullable + public String getName(@Nullable final String lineText, final OnigCaptureIndex @Nullable [] captureIndices) { + final var name = this.name; + if (!nameIsCapturing || name == null || lineText == null || captureIndices == null) { + return name; + } + return RegexSource.replaceCaptures(name, lineText, captureIndices); + } + + @Nullable + public String getContentName(final String lineText, final OnigCaptureIndex[] captureIndices) { + final var contentName = this.contentName; + if (!contentNameIsCapturing || contentName == null) { + return contentName; + } + return RegexSource.replaceCaptures(contentName, lineText, captureIndices); + } + + public abstract void collectPatternsRecursive(IRuleRegistry grammar, RegExpSourceList out, boolean isFirst); + + public abstract CompiledRule compile(IRuleRegistry grammar, @Nullable String endRegexSource); + + public abstract CompiledRule compileAG(IRuleRegistry grammar, @Nullable String endRegexSource, boolean allowA, + boolean allowG); + } \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/RuleFactory.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/RuleFactory.java index c5dd96a44..6c88aa4e1 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/RuleFactory.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/RuleFactory.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,232 +11,255 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.rule; - + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.rule; + +import static java.lang.System.Logger.Level.*; +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import java.lang.System.Logger; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.grammar.RawRepository; +import org.eclipse.tm4e.core.internal.grammar.RawRule; import org.eclipse.tm4e.core.internal.types.IRawCaptures; import org.eclipse.tm4e.core.internal.types.IRawGrammar; import org.eclipse.tm4e.core.internal.types.IRawRepository; import org.eclipse.tm4e.core.internal.types.IRawRule; -import org.eclipse.tm4e.core.internal.utils.CloneUtils; - -/** - * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts - * - */ -public class RuleFactory { - - public static CaptureRule createCaptureRule(IRuleFactoryHelper helper, final String name, final String contentName, - final Integer retokenizeCapturedWithRuleId) { - return (CaptureRule) helper.registerRule(id -> new CaptureRule(id, name, contentName, retokenizeCapturedWithRuleId)); - } - - public static int getCompiledRuleId(final IRawRule desc, final IRuleFactoryHelper helper, - final IRawRepository repository) { - if (desc.getId() == null) { - - helper.registerRule(id -> { - desc.setId(id); - - if (desc.getMatch() != null) { - return new MatchRule(desc.getId(), desc.getName(), desc.getMatch(), - RuleFactory.compileCaptures(desc.getCaptures(), helper, repository)); - } - - if (desc.getBegin() == null) { - IRawRepository r = repository; - if (desc.getRepository() != null) { - r = CloneUtils.mergeObjects(repository, desc.getRepository()); - } - return new IncludeOnlyRule(desc.getId(), desc.getName(), desc.getContentName(), - RuleFactory._compilePatterns(desc.getPatterns(), helper, r)); - } - - String ruleWhile = desc.getWhile(); - if (ruleWhile != null) { - return new BeginWhileRule( - /* desc.$vscodeTextmateLocation, */ - desc.getId(), desc.getName(), desc.getContentName(), desc.getBegin(), - RuleFactory.compileCaptures( - desc.getBeginCaptures() != null ? desc.getBeginCaptures() : desc.getCaptures(), - helper, repository), - ruleWhile, - RuleFactory.compileCaptures( - desc.getWhileCaptures() != null ? desc.getWhileCaptures() : desc.getCaptures(), - helper, repository), - RuleFactory._compilePatterns(desc.getPatterns(), helper, repository)); - } - - return new BeginEndRule(desc.getId(), desc.getName(), desc.getContentName(), desc.getBegin(), - RuleFactory.compileCaptures( - desc.getBeginCaptures() != null ? desc.getBeginCaptures() : desc.getCaptures(), - helper, repository), - desc.getEnd(), - RuleFactory.compileCaptures( - desc.getEndCaptures() != null ? desc.getEndCaptures() : desc.getCaptures(), helper, - repository), - desc.isApplyEndPatternLast(), - RuleFactory._compilePatterns(desc.getPatterns(), helper, repository)); - }); + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/rule.ts + */ +public final class RuleFactory { + + private static final Logger LOGGER = System.getLogger(RuleFactory.class.getName()); + + private static CaptureRule createCaptureRule(final IRuleFactoryHelper helper, @Nullable final String name, + @Nullable final String contentName, @Nullable final Integer retokenizeCapturedWithRuleId) { + return helper.registerRule(id -> new CaptureRule(id, name, contentName, retokenizeCapturedWithRuleId)); + } + + public static int getCompiledRuleId(final IRawRule desc, final IRuleFactoryHelper helper, + final IRawRepository repository) { + if (desc.getId() == null) { + helper.registerRule(ruleId -> { + desc.setId(ruleId); + + final var ruleMatch = desc.getMatch(); + if (ruleMatch != null) { + return new MatchRule(ruleId, desc.getName(), ruleMatch, + compileCaptures(desc.getCaptures(), helper, repository)); + } + + final var begin = desc.getBegin(); + if (begin == null) { + final var repository1 = desc.getRepository() == null + ? repository + : IRawRepository.merge(repository, desc.getRepository()); + var patterns = desc.getPatterns(); + if (patterns == null && desc.getInclude() != null) { + final var includeRule = new RawRule(); + includeRule.setInclude(desc.getInclude()); + patterns = List.of(includeRule); + } + return new IncludeOnlyRule( + /* desc.$vscodeTextmateLocation, */ + ruleId, + desc.getName(), + desc.getContentName(), + compilePatterns(patterns, helper, repository1)); + } + + final String ruleWhile = desc.getWhile(); + if (ruleWhile != null) { + return new BeginWhileRule( + /* desc.$vscodeTextmateLocation, */ + ruleId, + desc.getName(), + desc.getContentName(), + begin, compileCaptures( + desc.getBeginCaptures() != null ? desc.getBeginCaptures() : desc.getCaptures(), + helper, repository), + ruleWhile, compileCaptures( + desc.getWhileCaptures() != null ? desc.getWhileCaptures() : desc.getCaptures(), + helper, repository), + compilePatterns(desc.getPatterns(), helper, repository)); + } + + return new BeginEndRule( + /* desc.$vscodeTextmateLocation, */ + ruleId, + desc.getName(), + desc.getContentName(), + begin, compileCaptures( + desc.getBeginCaptures() != null ? desc.getBeginCaptures() : desc.getCaptures(), + helper, repository), + desc.getEnd(), compileCaptures( + desc.getEndCaptures() != null ? desc.getEndCaptures() : desc.getCaptures(), helper, + repository), + desc.isApplyEndPatternLast(), + compilePatterns(desc.getPatterns(), helper, repository)); + }); + } + return castNonNull(desc.getId()); + } + + private static List<@Nullable CaptureRule> compileCaptures(@Nullable final IRawCaptures captures, + final IRuleFactoryHelper helper, final IRawRepository repository) { + if (captures == null) { + return Collections.emptyList(); + } + + // Find the maximum capture id + int maximumCaptureId = 0; + for (final String captureId : captures.getCaptureIds()) { + final int numericCaptureId = parseInt(captureId, 10); + if (numericCaptureId > maximumCaptureId) { + maximumCaptureId = numericCaptureId; + } } - return desc.getId(); - } - - private static List compileCaptures(IRawCaptures captures, IRuleFactoryHelper helper, - IRawRepository repository) { - List r = new ArrayList<>(); - int numericCaptureId; - int maximumCaptureId; - int i; - - if (captures != null) { - // Find the maximum capture id - maximumCaptureId = 0; - for (String captureId : captures) { - numericCaptureId = parseInt(captureId, 10); - if (numericCaptureId > maximumCaptureId) { - maximumCaptureId = numericCaptureId; - } - } - - // Initialize result - for (i = 0; i <= maximumCaptureId; i++) { - r.add(null); - } - - // Fill out result - for (String captureId : captures) { - numericCaptureId = parseInt(captureId, 10); - Integer retokenizeCapturedWithRuleId = null; - IRawRule rule = captures.getCapture(captureId); - if (rule.getPatterns() != null) { - retokenizeCapturedWithRuleId = RuleFactory.getCompiledRuleId(captures.getCapture(captureId), helper, - repository); - } - r.set(numericCaptureId, RuleFactory.createCaptureRule(helper, rule.getName(), rule.getContentName(), - retokenizeCapturedWithRuleId)); - } - } - - return r; - } - - private static int parseInt(String string, int base) { - try { - return Integer.parseInt(string, base); - } catch (Throwable e) { - return 0; - } - } - - private static ICompilePatternsResult _compilePatterns(Collection patterns, IRuleFactoryHelper helper, - IRawRepository repository) { - Collection r = new ArrayList(); - int patternId; - IRawGrammar externalGrammar; - Rule rule; - boolean skipRule; - - if (patterns != null) { - for (IRawRule pattern : patterns) { - patternId = -1; - - if (pattern.getInclude() != null) { - if (pattern.getInclude().charAt(0) == '#') { - // Local include found in `repository` - IRawRule localIncludedRule = repository.getProp(pattern.getInclude().substring(1)); - if (localIncludedRule != null) { - patternId = RuleFactory.getCompiledRuleId(localIncludedRule, helper, repository); - } else { - // console.warn('CANNOT find rule for scopeName: ' + - // pattern.include + ', I am: ', - // repository['$base'].name); - } - } else if (pattern.getInclude().equals("$base") || pattern.getInclude().equals("$self")) { - // Special include also found in `repository` - patternId = RuleFactory.getCompiledRuleId(repository.getProp(pattern.getInclude()), helper, - repository); - } else { - String externalGrammarName = null, externalGrammarInclude = null; - int sharpIndex = pattern.getInclude().indexOf('#'); - if (sharpIndex >= 0) { - externalGrammarName = pattern.getInclude().substring(0, sharpIndex); - externalGrammarInclude = pattern.getInclude().substring(sharpIndex + 1); - } else { - externalGrammarName = pattern.getInclude(); - } - // External include - externalGrammar = helper.getExternalGrammar(externalGrammarName, repository); - - if (externalGrammar != null) { - if (externalGrammarInclude != null) { - IRawRule externalIncludedRule = externalGrammar.getRepository() - .getProp(externalGrammarInclude); - if (externalIncludedRule != null) { - patternId = RuleFactory.getCompiledRuleId(externalIncludedRule, helper, - externalGrammar.getRepository()); - } else { - // console.warn('CANNOT find rule for - // scopeName: ' + pattern.include + ', I am: - // ', repository['$base'].name); - } - } else { - patternId = RuleFactory.getCompiledRuleId(externalGrammar.getRepository().getSelf(), - helper, externalGrammar.getRepository()); - } - } else { - // console.warn('CANNOT find grammar for scopeName: - // ' + pattern.include + ', I am: ', - // repository['$base'].name); - } - - } - } else { - patternId = RuleFactory.getCompiledRuleId(pattern, helper, repository); - } - - if (patternId != -1) { - rule = helper.getRule(patternId); - - skipRule = false; - - if (rule instanceof IncludeOnlyRule) { - IncludeOnlyRule ior = (IncludeOnlyRule) rule; - if (ior.hasMissingPatterns && ior.patterns.length == 0) { - skipRule = true; - } - } else if (rule instanceof BeginEndRule) { - BeginEndRule br = (BeginEndRule) rule; - if (br.hasMissingPatterns && br.patterns.length == 0) { - skipRule = true; - } - } else if (rule instanceof BeginWhileRule) { - BeginWhileRule br = (BeginWhileRule) rule; - if (br.hasMissingPatterns && br.patterns.length == 0) { - skipRule = true; - } - } - - if (skipRule) { - // console.log('REMOVING RULE ENTIRELY DUE TO EMPTY - // PATTERNS THAT ARE MISSING'); - continue; - } - - r.add(patternId); - } - } - } - - return new ICompilePatternsResult(r, ((patterns != null ? patterns.size() : 0) != r.size())); - } - -} + // Initialize result + final var r = new ArrayList<@Nullable CaptureRule>(); + for (int i = 0; i <= maximumCaptureId; i++) { + r.add(null); + } + + // Fill out result + for (final String captureId : captures.getCaptureIds()) { + final int numericCaptureId = parseInt(captureId, 10); + final IRawRule rule = captures.getCapture(captureId); + final Integer retokenizeCapturedWithRuleId = rule.getPatterns() == null + ? null + : getCompiledRuleId(captures.getCapture(captureId), helper, repository); + r.set(numericCaptureId, createCaptureRule(helper, rule.getName(), rule.getContentName(), + retokenizeCapturedWithRuleId)); + } + return r; + } + + private static int parseInt(final String string, final int base) { + try { + return Integer.parseInt(string, base); + } catch (final NumberFormatException ex) { + return 0; + } + } + + private static CompilePatternsResult compilePatterns(@Nullable final Collection patterns, + final IRuleFactoryHelper helper, final IRawRepository repository) { + if (patterns == null) { + return new CompilePatternsResult(new int[0], false); + } + + final var r = new ArrayList(); + for (final IRawRule pattern : patterns) { + int patternId = -1; + final var patternInclude = pattern.getInclude(); + if (patternInclude == null) { + patternId = getCompiledRuleId(pattern, helper, repository); + } else { + if (patternInclude.charAt(0) == '#') { + // Local include found in `repository` + final IRawRule localIncludedRule = repository.getRule(patternInclude.substring(1)); + if (localIncludedRule != null) { + patternId = getCompiledRuleId(localIncludedRule, helper, repository); + } else if (LOGGER.isLoggable(DEBUG)) { + LOGGER.log(DEBUG, "CANNOT find rule for scopeName: %s, I am: %s", + patternInclude, repository.getBase().getName()); + } + } else if (patternInclude.equals(RawRepository.DOLLAR_BASE)) { // Special include also found in + // `repository` + patternId = getCompiledRuleId(repository.getBase(), helper, repository); + } else if (patternInclude.equals(RawRepository.DOLLAR_SELF)) { // Special include also found in + // `repository` + patternId = getCompiledRuleId(repository.getSelf(), helper, repository); + } else { + final String externalGrammarName; + final String externalGrammarInclude; + final int sharpIndex = patternInclude.indexOf('#'); + if (sharpIndex >= 0) { + externalGrammarName = patternInclude.substring(0, sharpIndex); + externalGrammarInclude = patternInclude.substring(sharpIndex + 1); + } else { + externalGrammarName = patternInclude; + externalGrammarInclude = null; + } + + // External include + final IRawGrammar externalGrammar = helper.getExternalGrammar(externalGrammarName, repository); + if (externalGrammar != null) { + final var externalGrammarRepo = externalGrammar.getRepository(); + if (externalGrammarInclude != null) { + final IRawRule externalIncludedRule = externalGrammarRepo.getRule(externalGrammarInclude); + if (externalIncludedRule != null) { + patternId = getCompiledRuleId(externalIncludedRule, helper, externalGrammarRepo); + } else if (LOGGER.isLoggable(DEBUG)) { + LOGGER.log(DEBUG, "CANNOT find rule for scopeName: %s, I am: %s", + patternInclude, repository.getBase().getName()); + } + } else { + patternId = getCompiledRuleId(externalGrammarRepo.getSelf(), helper, externalGrammarRepo); + } + } else if (LOGGER.isLoggable(DEBUG)) { + LOGGER.log(DEBUG, "CANNOT find grammar for scopeName: %s, I am: %s", + patternInclude, repository.getBase().getName()); + } + } + } + + if (patternId != -1) { + Rule rule; + try { + rule = helper.getRule(patternId); + } catch (final IndexOutOfBoundsException ex) { + rule = null; + if (patternInclude != null) { + // TODO currently happens if an include rule references another not yet parsed rule + } else { + // should never happen + ex.printStackTrace(); + } + } + boolean skipRule = false; + + if (rule instanceof IncludeOnlyRule) { + final var ior = (IncludeOnlyRule) rule; + if (ior.hasMissingPatterns && ior.patterns.length == 0) { + skipRule = true; + } + } else if (rule instanceof BeginEndRule) { + final var ber = (BeginEndRule) rule; + if (ber.hasMissingPatterns && ber.patterns.length == 0) { + skipRule = true; + } + } else if (rule instanceof BeginWhileRule) { + final var bwr = (BeginWhileRule) rule; + if (bwr.hasMissingPatterns && bwr.patterns.length == 0) { + skipRule = true; + } + } + + if (skipRule) { + LOGGER.log(DEBUG, "REMOVING RULE ENTIRELY DUE TO EMPTY PATTERNS THAT ARE MISSING"); + continue; + } + + r.add(patternId); + } + } + + return new CompilePatternsResult(r.stream().mapToInt(Integer::intValue).toArray(), patterns.size() != r.size()); + } + + private RuleFactory() { + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/package-info.java new file mode 100644 index 000000000..95f07f89b --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/rule/package-info.java @@ -0,0 +1,8 @@ +/** + * Types in this package are modeled after github.com/Microsoft/vscode-textmate/blob/main/src/rule.ts + */ +@NonNullByDefault +package org.eclipse.tm4e.core.internal.rule; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/ColorMap.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/ColorMap.java new file mode 100644 index 000000000..a0ac295c7 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/ColorMap.java @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.TMException; + +public class ColorMap { + + private boolean isFrozen; + private int lastColorId = 0; + private final List id2color = new ArrayList<>(); + private final Map color2id = new LinkedHashMap<>(); + + public ColorMap() { + this(null); + } + + public ColorMap(@Nullable final List colorMap) { + if (colorMap != null) { + this.isFrozen = true; + for (int i = 0, len = colorMap.size(); i < len; i++) { + this.color2id.put(colorMap.get(i), i); + this.id2color.add(colorMap.get(i)); + } + } else { + this.isFrozen = false; + } + } + + public int getId(@Nullable String color) { + if (color == null) { + return 0; + } + color = color.toUpperCase(); + Integer value = color2id.get(color); + if (value != null) { + return value; + } + if (this.isFrozen) { + throw new TMException("Missing color in color map - " + color); + } + value = ++lastColorId; + color2id.put(castNonNull(color), value); + if (value >= id2color.size()) { + id2color.add(castNonNull(color)); + } else { + id2color.set(value, castNonNull(color)); + } + return value; + } + + @Nullable + public String getColor(final int id) { + for (final var entry : color2id.entrySet()) { + if (id == entry.getValue()) { + return entry.getKey(); + } + } + return null; + } + + public Set getColorMap() { + return color2id.keySet(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + color2id.hashCode(); + result = prime * result + lastColorId; + return result; + } + + @Override + public boolean equals(@Nullable final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final ColorMap other = (ColorMap) obj; + return Objects.equals(color2id, other.color2id) && lastColorId == other.lastColorId; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/FontStyle.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/FontStyle.java similarity index 51% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/FontStyle.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/FontStyle.java index a8664763f..7bdcf04a4 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/FontStyle.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/FontStyle.java @@ -1,30 +1,34 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.theme; - -/** - * Font style definitions. - * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/theme.ts - * - */ -public class FontStyle { - - public static final int NotSet = -1; - - // This can are bit-flags, so it can be `Italic | Bold` - public static final int None = 0; - public static final int Italic = 1; - public static final int Bold = 2; - public static final int Underline = 4; - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme; + +/** + * Font style definitions. + * + * @see + * github.com/microsoft/vscode-textmate/blob/master/src/theme.ts + */ +public final class FontStyle { + + public static final int NotSet = -1; + + // This can are bit-flags, so it can be `Italic | Bold` + public static final int None = 0; + public static final int Italic = 1; + public static final int Bold = 2; + public static final int Underline = 4; + public static final int Strikethrough = 8; + + private FontStyle() { + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/IRawTheme.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/IRawTheme.java similarity index 81% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/IRawTheme.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/IRawTheme.java index f345cf3a2..bba1cca52 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/IRawTheme.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/IRawTheme.java @@ -9,14 +9,18 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.core.theme; - -import java.util.Collection; - -public interface IRawTheme { - - String getName(); - - Collection getSettings(); - -} +package org.eclipse.tm4e.core.internal.theme; + +import java.util.Collection; + +import org.eclipse.jdt.annotation.Nullable; + +public interface IRawTheme { + + @Nullable + String getName(); + + @Nullable + Collection getSettings(); + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/PListTheme.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/IRawThemeSetting.java similarity index 52% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/PListTheme.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/IRawThemeSetting.java index 83144cc74..8e2089af0 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/PListTheme.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/IRawThemeSetting.java @@ -9,21 +9,25 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.core.internal.theme; - -import java.util.Map; - -import org.eclipse.tm4e.core.internal.parser.PListObject; - -public class PListTheme extends PListObject { - - public PListTheme(PListObject parent, boolean valueAsArray) { - super(parent, valueAsArray); - } - - @Override - protected Map createRaw() { - return new ThemeRaw(); - } - -} +package org.eclipse.tm4e.core.internal.theme; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * A single theme setting. + * + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/main.ts + */ +public interface IRawThemeSetting { + + @Nullable + String getName(); + + @Nullable + Object getScope(); + + @Nullable + IThemeSetting getSetting(); + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/IThemeProvider.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/IThemeProvider.java similarity index 91% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/IThemeProvider.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/IThemeProvider.java index 1c61e6537..3a2099a9b 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/IThemeProvider.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/IThemeProvider.java @@ -9,14 +9,14 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.core.theme; - -import java.util.List; - -public interface IThemeProvider { - - List themeMatch(String scopeName); - - ThemeTrieElementRule getDefaults(); - -} +package org.eclipse.tm4e.core.internal.theme; + +import java.util.List; + +public interface IThemeProvider { + + List themeMatch(String scopeName); + + ThemeTrieElementRule getDefaults(); + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/IThemeSetting.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/IThemeSetting.java similarity index 78% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/IThemeSetting.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/IThemeSetting.java index b2129f03e..72b4f7aae 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/IThemeSetting.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/IThemeSetting.java @@ -9,13 +9,18 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.core.theme; - -public interface IThemeSetting { - - Object getFontStyle(); - - String getBackground(); - - String getForeground(); -} +package org.eclipse.tm4e.core.internal.theme; + +import org.eclipse.jdt.annotation.Nullable; + +public interface IThemeSetting { + + @Nullable + Object getFontStyle(); + + @Nullable + String getBackground(); + + @Nullable + String getForeground(); +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/ParsedThemeRule.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/ParsedThemeRule.java new file mode 100644 index 000000000..b7e5d5b80 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/ParsedThemeRule.java @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme; + +import java.util.List; +import java.util.Objects; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/theme.ts + */ +public class ParsedThemeRule { + + public final String scope; + + @Nullable + public final List parentScopes; + + public final int index; + + /** + * -1 if not set. An or mask of `FontStyle` otherwise. + */ + public final int fontStyle; + + @Nullable + public final String foreground; + + @Nullable + public final String background; + + public ParsedThemeRule(final String scope, @Nullable final List parentScopes, final int index, + final int fontStyle, @Nullable final String foreground, @Nullable final String background) { + this.scope = scope; + this.parentScopes = parentScopes; + this.index = index; + this.fontStyle = fontStyle; + this.foreground = foreground; + this.background = background; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + fontStyle; + result = prime * result + index; + result = prime * result + Objects.hash(background, foreground, parentScopes, scope); + return result; + } + + @Override + public boolean equals(@Nullable final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final ParsedThemeRule other = (ParsedThemeRule) obj; + return Objects.equals(background, other.background) && fontStyle == other.fontStyle + && Objects.equals(foreground, other.foreground) && index == other.index + && Objects.equals(parentScopes, other.parentScopes) && Objects.equals(scope, other.scope); + } + + @Override + public String toString() { + return "ParsedThemeRule [scope=" + scope + ", parentScopes=" + parentScopes + ", index=" + index + + ", fontStyle=" + fontStyle + ", foreground=" + foreground + ", background=" + background + "]"; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/Theme.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/Theme.java new file mode 100644 index 000000000..a0dcf8379 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/Theme.java @@ -0,0 +1,291 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme; + +import static org.eclipse.tm4e.core.internal.utils.MoreCollections.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.regex.Pattern; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.utils.CompareUtils; + +import com.google.common.base.Splitter; +import com.google.common.collect.Lists; + +/** + * TextMate theme. + * + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/theme.ts + */ +public class Theme { + + private static final Splitter BY_COMMA_SPLITTER = Splitter.on(','); + private static final Splitter BY_SPACE_SPLITTER = Splitter.on(' '); + + private static final Pattern RRGGBB = Pattern.compile("^#[0-9a-f]{6}", Pattern.CASE_INSENSITIVE); + private static final Pattern RRGGBBAA = Pattern.compile("^#[0-9a-f]{8}", Pattern.CASE_INSENSITIVE); + private static final Pattern RGB = Pattern.compile("^#[0-9a-f]{3}", Pattern.CASE_INSENSITIVE); + private static final Pattern RGBA = Pattern.compile("^#[0-9a-f]{4}", Pattern.CASE_INSENSITIVE); + + public static Theme createFromRawTheme(@Nullable final IRawTheme source, @Nullable final List colorMap) { + return createFromParsedTheme(parseTheme(source), colorMap); + } + + public static Theme createFromParsedTheme(final List source, @Nullable final List colorMap) { + return resolveParsedThemeRules(source, colorMap); + } + + private final ColorMap colorMap; + private final ThemeTrieElement root; + private final ThemeTrieElementRule defaults; + private final Map> cache = new HashMap<>(); + + public Theme(final ColorMap colorMap, final ThemeTrieElementRule defaults, final ThemeTrieElement root) { + this.colorMap = colorMap; + this.root = root; + this.defaults = defaults; + } + + public Set getColorMap() { + return this.colorMap.getColorMap(); + } + + public ThemeTrieElementRule getDefaults() { + return this.defaults; + } + + public List match(final String scopeName) { + if (!this.cache.containsKey(scopeName)) { + this.cache.put(scopeName, this.root.match(scopeName)); + } + return this.cache.get(scopeName); + } + + /** + * Parse a raw theme into rules. + */ + public static List parseTheme(@Nullable final IRawTheme source) { + if (source == null) { + return Collections.emptyList(); + } + + final var settings = source.getSettings(); + if (settings == null) { + return Collections.emptyList(); + } + + final List result = new ArrayList<>(); + int i = -1; + for (final IRawThemeSetting entry : settings) { + final var entrySetting = entry.getSetting(); + if (entrySetting == null) { + continue; + } + + i++; + + final Object settingScope = entry.getScope(); + List scopes; + if (settingScope instanceof String) { + String scope = (String) settingScope; + + // remove leading commas + scope = scope.replaceAll("^[,]+", ""); + + // remove trailing commas + scope = scope.replaceAll("[,]+$", ""); + + scopes = BY_COMMA_SPLITTER.splitToList(scope); + } else if (settingScope instanceof List) { + @SuppressWarnings("unchecked") + final var settingScopes = (List) settingScope; + scopes = settingScopes; + } else { + scopes = Arrays.asList(""); + } + + int fontStyle = FontStyle.NotSet; + final Object settingsFontStyle = entrySetting.getFontStyle(); + if (settingsFontStyle instanceof String) { + fontStyle = FontStyle.None; + + final Iterable segments = BY_SPACE_SPLITTER.split((String) settingsFontStyle); + for (final String segment : segments) { + switch (segment) { + case "italic": + fontStyle = fontStyle | FontStyle.Italic; + break; + case "bold": + fontStyle = fontStyle | FontStyle.Bold; + break; + case "underline": + fontStyle = fontStyle | FontStyle.Underline; + break; + case "strikethrough": + fontStyle = fontStyle | FontStyle.Strikethrough; + break; + } + } + } + + String foreground = null; + final Object settingsForeground = entrySetting.getForeground(); + if (settingsForeground instanceof String && isValidHexColor((String) settingsForeground)) { + foreground = (String) settingsForeground; + } + + String background = null; + final Object settingsBackground = entrySetting.getBackground(); + if (settingsBackground instanceof String && isValidHexColor((String) settingsBackground)) { + background = (String) settingsBackground; + } + + for (int j = 0, lenJ = scopes.size(); j < lenJ; j++) { + final String _scope = scopes.get(j).trim(); + + final List segments = BY_SPACE_SPLITTER.splitToList(_scope); + + final String scope = getLastElement(segments); + List parentScopes = null; + if (segments.size() > 1) { + parentScopes = segments.subList(0, segments.size() - 1); + parentScopes = Lists.reverse(parentScopes); + } + + result.add(new ParsedThemeRule(scope, parentScopes, i, fontStyle, foreground, background)); + } + } + + return result; + } + + /** + * Resolve rules (i.e. inheritance). + */ + public static Theme resolveParsedThemeRules(final List _parsedThemeRules, + @Nullable final List _colorMap) { + + // copy the list since we cannot be sure the given list is mutable + final var parsedThemeRules = new ArrayList<>(_parsedThemeRules); + + // Sort rules lexicographically, and then by index if necessary + parsedThemeRules.sort((a, b) -> { + int r = CompareUtils.strcmp(a.scope, b.scope); + if (r != 0) { + return r; + } + r = CompareUtils.strArrCmp(a.parentScopes, b.parentScopes); + if (r != 0) { + return r; + } + return a.index - b.index; + }); + + // Determine defaults + int defaultFontStyle = FontStyle.None; + String defaultForeground = "#000000"; + String defaultBackground = "#ffffff"; + while (!parsedThemeRules.isEmpty() && parsedThemeRules.get(0).scope.isEmpty()) { + final var incomingDefaults = parsedThemeRules.remove(0); + if (incomingDefaults.fontStyle != FontStyle.NotSet) { + defaultFontStyle = incomingDefaults.fontStyle; + } + if (incomingDefaults.foreground != null) { + defaultForeground = incomingDefaults.foreground; + } + if (incomingDefaults.background != null) { + defaultBackground = incomingDefaults.background; + } + } + final var colorMap = new ColorMap(_colorMap); + final var defaults = new ThemeTrieElementRule(0, null, defaultFontStyle, colorMap.getId(defaultForeground), + colorMap.getId(defaultBackground)); + + final var root = new ThemeTrieElement(new ThemeTrieElementRule(0, null, FontStyle.NotSet, 0, 0), + Collections.emptyList()); + for (final var rule : parsedThemeRules) { + root.insert(0, rule.scope, rule.parentScopes, rule.fontStyle, colorMap.getId(rule.foreground), + colorMap.getId(rule.background)); + } + + return new Theme(colorMap, defaults, root); + } + + private static boolean isValidHexColor(final String hex) { + if (hex.isEmpty()) { + return false; + } + + if (RRGGBB.matcher(hex).matches()) { + // #rrggbb + return true; + } + + if (RRGGBBAA.matcher(hex).matches()) { + // #rrggbbaa + return true; + } + + if (RGB.matcher(hex).matches()) { + // #rgb + return true; + } + + if (RGBA.matcher(hex).matches()) { + // #rgba + return true; + } + + return false; + } + + @Nullable + public String getColor(final int id) { + return this.colorMap.getColor(id); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + cache.hashCode(); + result = prime * result + colorMap.hashCode(); + result = prime * result + defaults.hashCode(); + result = prime * result + root.hashCode(); + return result; + } + + @Override + public boolean equals(@Nullable final Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + final Theme other = (Theme) obj; + return Objects.equals(cache, other.cache) + && Objects.equals(colorMap, other.colorMap) + && Objects.equals(defaults, other.defaults) + && Objects.equals(root, other.root); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeRaw.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeRaw.java index 2474837aa..f39b0c5db 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeRaw.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeRaw.java @@ -9,52 +9,64 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.core.internal.theme; - +package org.eclipse.tm4e.core.internal.theme; + import java.util.Collection; import java.util.HashMap; -import org.eclipse.tm4e.core.theme.IRawTheme; -import org.eclipse.tm4e.core.theme.IRawThemeSetting; -import org.eclipse.tm4e.core.theme.IThemeSetting; - -public class ThemeRaw extends HashMap implements IRawTheme, IRawThemeSetting, IThemeSetting { - - private static final long serialVersionUID = -3622927264735492387L; - - @Override - public String getName() { - return (String) super.get("name"); - } - - @Override - public Collection getSettings() { - return (Collection) super.get("settings"); - } - - @Override - public Object getScope() { - return super.get("scope"); - } - - @Override - public IThemeSetting getSetting() { - return (IThemeSetting) super.get("settings"); - } - - @Override - public Object getFontStyle() { - return super.get("fontStyle"); - } - - @Override - public String getBackground() { - return (String) super.get("background"); - } - - @Override - public String getForeground() { - return (String) super.get("foreground"); - } - -} +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.parser.PropertySettable; + +public final class ThemeRaw extends HashMap + implements IRawTheme, IRawThemeSetting, IThemeSetting, PropertySettable { + + private static final long serialVersionUID = 1L; + + @Nullable + @Override + public String getName() { + return (String) super.get("name"); + } + + @SuppressWarnings("unchecked") + @Nullable + @Override + public Collection getSettings() { + return (Collection) super.get("settings"); + } + + @Nullable + @Override + public Object getScope() { + return super.get("scope"); + } + + @Nullable + @Override + public IThemeSetting getSetting() { + return (IThemeSetting) super.get("settings"); + } + + @Nullable + @Override + public Object getFontStyle() { + return super.get("fontStyle"); + } + + @Nullable + @Override + public String getBackground() { + return (String) super.get("background"); + } + + @Nullable + @Override + public String getForeground() { + return (String) super.get("foreground"); + } + + @Override + public void setProperty(final String name, final Object value) { + put(name, value); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/ThemeTrieElement.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeTrieElement.java similarity index 53% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/ThemeTrieElement.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeTrieElement.java index 286a4aaec..cf55af5d4 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/ThemeTrieElement.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeTrieElement.java @@ -1,187 +1,196 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.theme; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import org.eclipse.tm4e.core.internal.utils.CompareUtils; - -public class ThemeTrieElement { - - // _themeTrieElementBrand: void; - - private final ThemeTrieElementRule mainRule; - private final List rulesWithParentScopes; - private final Map children; - - public ThemeTrieElement(ThemeTrieElementRule mainRule) { - this(mainRule, new ArrayList<>(), new HashMap<>()); - } - - public ThemeTrieElement(ThemeTrieElementRule mainRule, List rulesWithParentScopes) { - this(mainRule, rulesWithParentScopes, new HashMap<>()); - } - - public ThemeTrieElement(ThemeTrieElementRule mainRule, List rulesWithParentScopes, - Map children) { - this.mainRule = mainRule; - this.rulesWithParentScopes = rulesWithParentScopes; - this.children = children; - } - - private static List sortBySpecificity(List arr) { - if (arr.size() == 1) { - return arr; - } - arr.sort(ThemeTrieElement::cmpBySpecificity); - return arr; - } - - private static int cmpBySpecificity(ThemeTrieElementRule a, ThemeTrieElementRule b) { - if (a.scopeDepth == b.scopeDepth) { - List aParentScopes = a.parentScopes; - List bParentScopes = b.parentScopes; - int aParentScopesLen = aParentScopes == null ? 0 : aParentScopes.size(); - int bParentScopesLen = bParentScopes == null ? 0 : bParentScopes.size(); - if (aParentScopesLen == bParentScopesLen) { - for (int i = 0; i < aParentScopesLen; i++) { - int aLen = aParentScopes.get(i).length(); - int bLen = bParentScopes.get(i).length(); - if (aLen != bLen) { - return bLen - aLen; - } - } - } - return bParentScopesLen - aParentScopesLen; - } - return b.scopeDepth - a.scopeDepth; - } - - public List match(String scope) { - if ("".equals(scope)) { - List arr = new ArrayList<>(); - arr.add(this.mainRule); - arr.addAll(this.rulesWithParentScopes); - return ThemeTrieElement.sortBySpecificity(arr); - } - - int dotIndex = scope.indexOf('.'); - String head; - String tail; - if (dotIndex == -1) { - head = scope; - tail = ""; - } else { - head = scope.substring(0, dotIndex); - tail = scope.substring(dotIndex + 1); - } - - if (this.children.containsKey(head)) { - return this.children.get(head).match(tail); - } - - List arr = new ArrayList<>(); - arr.add(this.mainRule); - arr.addAll(this.rulesWithParentScopes); - return ThemeTrieElement.sortBySpecificity(arr); - } - - public void insert(int scopeDepth, String scope, List parentScopes, int fontStyle, int foreground, - int background) { - if ("".equals(scope)) { - this.doInsertHere(scopeDepth, parentScopes, fontStyle, foreground, background); - return; - } - - int dotIndex = scope.indexOf('.'); - String head; - String tail; - if (dotIndex == -1) { - head = scope; - tail = ""; - } else { - head = scope.substring(0, dotIndex); - tail = scope.substring(dotIndex + 1); - } - - ThemeTrieElement child; - if (this.children.containsKey(head)) { - child = this.children.get(head); - } else { - child = new ThemeTrieElement(this.mainRule.clone(), - ThemeTrieElementRule.cloneArr(this.rulesWithParentScopes)); - this.children.put(head, child); - } - - child.insert(scopeDepth + 1, tail, parentScopes, fontStyle, foreground, background); - } - - private void doInsertHere(int scopeDepth, List parentScopes, int fontStyle, int foreground, - int background) { - - if (parentScopes == null) { - // Merge into the main rule - this.mainRule.acceptOverwrite(scopeDepth, fontStyle, foreground, background); - return; - } - - // Try to merge into existing rule - for (ThemeTrieElementRule rule : this.rulesWithParentScopes) { - if (CompareUtils.strArrCmp(rule.parentScopes, parentScopes) == 0) { - // bingo! => we get to merge this into an existing one - rule.acceptOverwrite(scopeDepth, fontStyle, foreground, background); - return; - } - } - - // Must add a new rule - - // Inherit from main rule - if (fontStyle == FontStyle.NotSet) { - fontStyle = this.mainRule.fontStyle; - } - if (foreground == 0) { - foreground = this.mainRule.foreground; - } - if (background == 0) { - background = this.mainRule.background; - } - - this.rulesWithParentScopes - .add(new ThemeTrieElementRule(scopeDepth, parentScopes, fontStyle, foreground, background)); - } - - @Override - public int hashCode() { - return Objects.hash(children, mainRule, rulesWithParentScopes); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ThemeTrieElement other = (ThemeTrieElement) obj; - return Objects.equals(children, other.children) && Objects.equals(mainRule, other.mainRule) && Objects.equals(rulesWithParentScopes, other.rulesWithParentScopes); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.utils.CompareUtils; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/theme.ts + */ +public class ThemeTrieElement { + + private final ThemeTrieElementRule mainRule; + private final List rulesWithParentScopes; + private final Map children; + + public ThemeTrieElement(final ThemeTrieElementRule mainRule) { + this(mainRule, new ArrayList<>(), new HashMap<>()); + } + + public ThemeTrieElement(final ThemeTrieElementRule mainRule, + final List rulesWithParentScopes) { + this(mainRule, rulesWithParentScopes, new HashMap<>()); + } + + public ThemeTrieElement(final ThemeTrieElementRule mainRule, final List rulesWithParentScopes, + final Map children) { + this.mainRule = mainRule; + this.rulesWithParentScopes = rulesWithParentScopes; + this.children = children; + } + + private static List sortBySpecificity(final List arr) { + if (arr.size() == 1) { + return arr; + } + arr.sort(ThemeTrieElement::cmpBySpecificity); + return arr; + } + + private static int cmpBySpecificity(final ThemeTrieElementRule a, final ThemeTrieElementRule b) { + if (a.scopeDepth == b.scopeDepth) { + final var aParentScopes = a.parentScopes; + final var bParentScopes = b.parentScopes; + final int aParentScopesLen = aParentScopes == null ? 0 : aParentScopes.size(); + final int bParentScopesLen = bParentScopes == null ? 0 : bParentScopes.size(); + if (aParentScopesLen == bParentScopesLen) { + for (int i = 0; i < aParentScopesLen; i++) { + @SuppressWarnings("null") + final String aScope = aParentScopes.get(i); + @SuppressWarnings("null") + final String bScope = bParentScopes.get(i); + final int aLen = aScope.length(); + final int bLen = bScope.length(); + if (aLen != bLen) { + return bLen - aLen; + } + } + } + return bParentScopesLen - aParentScopesLen; + } + return b.scopeDepth - a.scopeDepth; + } + + public List match(final String scope) { + if ("".equals(scope)) { + final var arr = new ArrayList(); + arr.add(this.mainRule); + arr.addAll(this.rulesWithParentScopes); + return ThemeTrieElement.sortBySpecificity(arr); + } + + final int dotIndex = scope.indexOf('.'); + String head; + String tail; + if (dotIndex == -1) { + head = scope; + tail = ""; + } else { + head = scope.substring(0, dotIndex); + tail = scope.substring(dotIndex + 1); + } + + if (this.children.containsKey(head)) { + return this.children.get(head).match(tail); + } + + final var arr = new ArrayList(); + arr.add(this.mainRule); + arr.addAll(this.rulesWithParentScopes); + return ThemeTrieElement.sortBySpecificity(arr); + } + + public void insert(final int scopeDepth, final String scope, @Nullable final List parentScopes, + final int fontStyle, final int foreground, final int background) { + if (scope.isEmpty()) { + this.doInsertHere(scopeDepth, parentScopes, fontStyle, foreground, background); + return; + } + + final int dotIndex = scope.indexOf('.'); + String head; + String tail; + if (dotIndex == -1) { + head = scope; + tail = ""; + } else { + head = scope.substring(0, dotIndex); + tail = scope.substring(dotIndex + 1); + } + + ThemeTrieElement child; + if (this.children.containsKey(head)) { + child = this.children.get(head); + } else { + child = new ThemeTrieElement(this.mainRule.clone(), + ThemeTrieElementRule.cloneArr(this.rulesWithParentScopes)); + this.children.put(head, child); + } + + child.insert(scopeDepth + 1, tail, parentScopes, fontStyle, foreground, background); + } + + private void doInsertHere(final int scopeDepth, @Nullable final List parentScopes, int fontStyle, + int foreground, int background) { + + if (parentScopes == null) { + // Merge into the main rule + this.mainRule.acceptOverwrite(scopeDepth, fontStyle, foreground, background); + return; + } + + // Try to merge into existing rule + for (final ThemeTrieElementRule rule : this.rulesWithParentScopes) { + if (CompareUtils.strArrCmp(rule.parentScopes, parentScopes) == 0) { + // bingo! => we get to merge this into an existing one + rule.acceptOverwrite(scopeDepth, fontStyle, foreground, background); + return; + } + } + + // Must add a new rule + + // Inherit from main rule + if (fontStyle == FontStyle.NotSet) { + fontStyle = this.mainRule.fontStyle; + } + if (foreground == 0) { + foreground = this.mainRule.foreground; + } + if (background == 0) { + background = this.mainRule.background; + } + + this.rulesWithParentScopes.add( + new ThemeTrieElementRule(scopeDepth, parentScopes, fontStyle, foreground, background)); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + children.hashCode(); + result = prime * result + mainRule.hashCode(); + result = prime * result + rulesWithParentScopes.hashCode(); + return result; + } + + @Override + public boolean equals(@Nullable final Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + final ThemeTrieElement other = (ThemeTrieElement) obj; + return children.equals(other.children) + && mainRule.equals(other.mainRule) + && rulesWithParentScopes.equals(other.rulesWithParentScopes); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/ThemeTrieElementRule.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeTrieElementRule.java similarity index 51% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/ThemeTrieElementRule.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeTrieElementRule.java index e527f38cf..88b6c687a 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/ThemeTrieElementRule.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/ThemeTrieElementRule.java @@ -1,93 +1,106 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.theme; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -public class ThemeTrieElementRule { - - // _themeTrieElementRuleBrand: void; - - public int scopeDepth; - public final List parentScopes; - public int fontStyle; - public int foreground; - public int background; - - public ThemeTrieElementRule(int scopeDepth, List parentScopes, int fontStyle, int foreground, - int background) { - this.scopeDepth = scopeDepth; - this.parentScopes = parentScopes; - this.fontStyle = fontStyle; - this.foreground = foreground; - this.background = background; - } - - @Override - public ThemeTrieElementRule clone() { - return new ThemeTrieElementRule(this.scopeDepth, this.parentScopes, this.fontStyle, this.foreground, - this.background); - } - - public static List cloneArr(List arr) { - List r = new ArrayList<>(); - for (int i = 0, len = arr.size(); i < len; i++) { - r.add(arr.get(i).clone()); - } - return r; - } - - public void acceptOverwrite(int scopeDepth, int fontStyle, int foreground, int background) { - if (this.scopeDepth > scopeDepth) { - // TODO!!! - // console.log('how did this happen?'); - } else { - this.scopeDepth = scopeDepth; - } - // console.log('TODO -> my depth: ' + this.scopeDepth + ', overwriting - // depth: ' + scopeDepth); - if (fontStyle != FontStyle.NotSet) { - this.fontStyle = fontStyle; - } - if (foreground != 0) { - this.foreground = foreground; - } - if (background != 0) { - this.background = background; - } - } - - @Override - public int hashCode() { - return Objects.hash(background, fontStyle, foreground, parentScopes, scopeDepth); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ThemeTrieElementRule other = (ThemeTrieElementRule) obj; - return background == other.background && fontStyle == other.fontStyle && foreground == other.foreground && - Objects.equals(parentScopes, other.parentScopes) && scopeDepth == other.scopeDepth; - } - - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/theme.ts + */ +public class ThemeTrieElementRule { + + public int scopeDepth; + + @Nullable + public final List parentScopes; + + public int fontStyle; + public int foreground; + public int background; + + public ThemeTrieElementRule(final int scopeDepth, @Nullable final List parentScopes, final int fontStyle, + final int foreground, + final int background) { + this.scopeDepth = scopeDepth; + this.parentScopes = parentScopes; + this.fontStyle = fontStyle; + this.foreground = foreground; + this.background = background; + } + + @Override + public ThemeTrieElementRule clone() { + return new ThemeTrieElementRule(this.scopeDepth, this.parentScopes, this.fontStyle, this.foreground, + this.background); + } + + public static List cloneArr(final List arr) { + final var r = new ArrayList(arr.size()); + for (final var e : arr) { + r.add(e.clone()); + } + return r; + } + + public void acceptOverwrite(final int scopeDepth, final int fontStyle, final int foreground, final int background) { + if (this.scopeDepth > scopeDepth) { + // TODO!!! + // console.log('how did this happen?'); + } else { + this.scopeDepth = scopeDepth; + } + // console.log('TODO -> my depth: ' + this.scopeDepth + ', overwriting depth: ' + scopeDepth); + if (fontStyle != FontStyle.NotSet) { + this.fontStyle = fontStyle; + } + if (foreground != 0) { + this.foreground = foreground; + } + if (background != 0) { + this.background = background; + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + background; + result = prime * result + fontStyle; + result = prime * result + foreground; + result = prime * result + Objects.hashCode(parentScopes); + result = prime * result + scopeDepth; + return result; + } + + @Override + public boolean equals(@Nullable final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final ThemeTrieElementRule other = (ThemeTrieElementRule) obj; + return background == other.background && fontStyle == other.fontStyle && foreground == other.foreground && + Objects.equals(parentScopes, other.parentScopes) && scopeDepth == other.scopeDepth; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/AbstractAttributeCondition.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/AbstractAttributeCondition.java similarity index 82% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/AbstractAttributeCondition.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/AbstractAttributeCondition.java index ae07b83b4..0eb5cd168 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/AbstractAttributeCondition.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/AbstractAttributeCondition.java @@ -1,39 +1,39 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.css; - -import org.w3c.css.sac.AttributeCondition; - -public abstract class AbstractAttributeCondition implements AttributeCondition, ExtendedCondition { - - /** - * The attribute value. - */ - protected String value; - - /** - * Creates a new AbstractAttributeCondition object. - */ - protected AbstractAttributeCondition(String value) { - this.value = value; - } - - @Override - public String getValue() { - return value; - } - - @Override - public int getSpecificity() { - return 1 << 8; - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme.css; + +import org.w3c.css.sac.AttributeCondition; + +public abstract class AbstractAttributeCondition implements AttributeCondition, ExtendedCondition { + + /** + * The attribute value. + */ + private final String value; + + /** + * Creates a new AbstractAttributeCondition object. + */ + protected AbstractAttributeCondition(final String value) { + this.value = value; + } + + @Override + public String getValue() { + return value; + } + + @Override + public int getSpecificity() { + return 1 << 8; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/AbstractCombinatorCondition.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/AbstractCombinatorCondition.java similarity index 81% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/AbstractCombinatorCondition.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/AbstractCombinatorCondition.java index cb6dbf062..e6ab55e74 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/AbstractCombinatorCondition.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/AbstractCombinatorCondition.java @@ -1,44 +1,45 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.css; - -import org.w3c.css.sac.CombinatorCondition; -import org.w3c.css.sac.Condition; - -public abstract class AbstractCombinatorCondition implements CombinatorCondition, ExtendedCondition { - protected Condition firstCondition; - - protected Condition secondCondition; - - /** - * Creates a new CombinatorCondition object. - */ - protected AbstractCombinatorCondition(Condition c1, Condition c2) { - firstCondition = c1; - secondCondition = c2; - } - - @Override - public Condition getFirstCondition() { - return firstCondition; - } - - @Override - public Condition getSecondCondition() { - return secondCondition; - } - - public int getSpecificity() { - return ((ExtendedCondition) getFirstCondition()).getSpecificity() - + ((ExtendedCondition) getSecondCondition()).getSpecificity(); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme.css; + +import org.w3c.css.sac.CombinatorCondition; +import org.w3c.css.sac.Condition; + +public abstract class AbstractCombinatorCondition implements CombinatorCondition, ExtendedCondition { + + private final Condition firstCondition; + private final Condition secondCondition; + + /** + * Creates a new CombinatorCondition object. + */ + protected AbstractCombinatorCondition(final Condition c1, final Condition c2) { + firstCondition = c1; + secondCondition = c2; + } + + @Override + public Condition getFirstCondition() { + return firstCondition; + } + + @Override + public Condition getSecondCondition() { + return secondCondition; + } + + @Override + public int getSpecificity() { + return ((ExtendedCondition) getFirstCondition()).getSpecificity() + + ((ExtendedCondition) getSecondCondition()).getSpecificity(); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/AbstractElementSelector.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/AbstractElementSelector.java similarity index 61% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/AbstractElementSelector.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/AbstractElementSelector.java index 025c80127..58077fee4 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/AbstractElementSelector.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/AbstractElementSelector.java @@ -1,46 +1,51 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.css; - -import org.w3c.css.sac.ElementSelector; - -public abstract class AbstractElementSelector implements ElementSelector, ExtendedSelector { - - /** - * The namespace URI. - */ - protected String namespaceURI; - - /** - * The local name. - */ - protected String localName; - - /** - * Creates a new ElementSelector object. - */ - protected AbstractElementSelector(String uri, String name) { - namespaceURI = uri; - localName = name; - } - - @Override - public String getNamespaceURI() { - return namespaceURI; - } - - @Override - public String getLocalName() { - return localName; - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme.css; + +import org.eclipse.jdt.annotation.Nullable; +import org.w3c.css.sac.ElementSelector; + +public abstract class AbstractElementSelector implements ElementSelector, ExtendedSelector { + + /** + * The namespace URI. + */ + @Nullable + private final String namespaceURI; + + /** + * The local name. + */ + @Nullable + private final String localName; + + /** + * Creates a new ElementSelector object. + */ + protected AbstractElementSelector(@Nullable final String uri, @Nullable final String name) { + namespaceURI = uri; + localName = name; + } + + @Nullable + @Override + public String getNamespaceURI() { + return namespaceURI; + } + + @Nullable + @Override + public String getLocalName() { + return localName; + } + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSAndCondition.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSAndCondition.java similarity index 77% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSAndCondition.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSAndCondition.java index 914517303..6edc17550 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSAndCondition.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSAndCondition.java @@ -1,41 +1,41 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.css; - -import org.w3c.css.sac.Condition; - -public class CSSAndCondition extends AbstractCombinatorCondition { - - /** - * Creates a new CombinatorCondition object. - */ - public CSSAndCondition(Condition c1, Condition c2) { - super(c1, c2); - } - - @Override - public short getConditionType() { - return SAC_AND_CONDITION; - } - - @Override - public int nbMatch(String... names) { - return ((ExtendedCondition) getFirstCondition()).nbMatch(names) - + ((ExtendedCondition) getSecondCondition()).nbMatch(names); - } - - @Override - public int nbClass() { - return ((ExtendedCondition) getFirstCondition()).nbClass() - + ((ExtendedCondition) getSecondCondition()).nbClass(); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme.css; + +import org.w3c.css.sac.Condition; + +final class CSSAndCondition extends AbstractCombinatorCondition { + + /** + * Creates a new CombinatorCondition object. + */ + CSSAndCondition(final Condition c1, final Condition c2) { + super(c1, c2); + } + + @Override + public short getConditionType() { + return SAC_AND_CONDITION; + } + + @Override + public int nbMatch(final String... names) { + return ((ExtendedCondition) getFirstCondition()).nbMatch(names) + + ((ExtendedCondition) getSecondCondition()).nbMatch(names); + } + + @Override + public int nbClass() { + return ((ExtendedCondition) getFirstCondition()).nbClass() + + ((ExtendedCondition) getSecondCondition()).nbClass(); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSAttributeCondition.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSAttributeCondition.java similarity index 67% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSAttributeCondition.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSAttributeCondition.java index 7c518dbca..5b5de2957 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSAttributeCondition.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSAttributeCondition.java @@ -1,72 +1,79 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.css; - -public class CSSAttributeCondition extends AbstractAttributeCondition { - - /** - * The attribute's local name. - */ - protected String localName; - - /** - * The attribute's namespace URI. - */ - protected String namespaceURI; - - /** - * Whether this condition applies to specified attributes. - */ - protected boolean specified; - - public CSSAttributeCondition(String localName, String namespaceURI, boolean specified, String value) { - super(value); - this.localName = localName; - this.namespaceURI = namespaceURI; - this.specified = specified; - } - - @Override - public String getLocalName() { - return localName; - } - - @Override - public String getNamespaceURI() { - return namespaceURI; - } - - @Override - public boolean getSpecified() { - return specified; - } - - @Override - public short getConditionType() { - return SAC_ATTRIBUTE_CONDITION; - } - - @Override - public int nbMatch(String... names) { -// String val = getValue(); -// if (val == null) { -// return !e.getAttribute(getLocalName()).equals(""); -// } -// return e.getAttribute(getLocalName()).equals(val); - return 0; - } - - @Override - public int nbClass() { - return 0; - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme.css; + +import org.eclipse.jdt.annotation.Nullable; + +class CSSAttributeCondition extends AbstractAttributeCondition { + + /** + * The attribute's local name. + */ + @Nullable + private final String localName; + + /** + * The attribute's namespace URI. + */ + @Nullable + private final String namespaceURI; + + /** + * Whether this condition applies to specified attributes. + */ + private final boolean specified; + + protected CSSAttributeCondition(@Nullable final String localName, @Nullable final String namespaceURI, final boolean specified, final String value) { + super(value); + this.localName = localName; + this.namespaceURI = namespaceURI; + this.specified = specified; + } + + @Nullable + @Override + public String getLocalName() { + return localName; + } + + @Nullable + @Override + public String getNamespaceURI() { + return namespaceURI; + } + + @Override + public boolean getSpecified() { + return specified; + } + + @Override + public short getConditionType() { + return SAC_ATTRIBUTE_CONDITION; + } + + @Override + public int nbMatch(final String... names) { +// TODO +// String val = getValue(); +// if (val == null) { +// return !e.getAttribute(getLocalName()).equals(""); +// } +// return e.getAttribute(getLocalName()).equals(val); + return 0; + } + + @Override + public int nbClass() { + return 0; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSClassCondition.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSClassCondition.java similarity index 59% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSClassCondition.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSClassCondition.java index 2f6191086..ec941c6c6 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSClassCondition.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSClassCondition.java @@ -1,36 +1,38 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.css; - -public class CSSClassCondition extends CSSAttributeCondition { - - public CSSClassCondition(String localName, String namespaceURI, String value) { - super(localName, namespaceURI, true, value); - } - - @Override - public int nbMatch(String... names) { - String value = getValue(); - for (String name : names) { - if (name.equals(value)) { - return 1; - } - } - return 0; - } - - @Override - public int nbClass() { - return 1; - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme.css; + +import org.eclipse.jdt.annotation.Nullable; + +final class CSSClassCondition extends CSSAttributeCondition { + + CSSClassCondition(@Nullable final String localName, final String namespaceURI, final String value) { + super(localName, namespaceURI, true, value); + } + + @Override + public int nbMatch(final String... names) { + final String value = getValue(); + for (final String name : names) { + if (name.equals(value)) { + return 1; + } + } + return 0; + } + + @Override + public int nbClass() { + return 1; + } + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSConditionFactory.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSConditionFactory.java similarity index 51% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSConditionFactory.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSConditionFactory.java index c9ca35194..cab7041c0 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSConditionFactory.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSConditionFactory.java @@ -1,102 +1,103 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.css; - -import org.w3c.css.sac.AttributeCondition; -import org.w3c.css.sac.CSSException; -import org.w3c.css.sac.CombinatorCondition; -import org.w3c.css.sac.Condition; -import org.w3c.css.sac.ConditionFactory; -import org.w3c.css.sac.ContentCondition; -import org.w3c.css.sac.LangCondition; -import org.w3c.css.sac.NegativeCondition; -import org.w3c.css.sac.PositionalCondition; - -public class CSSConditionFactory implements ConditionFactory { - - public static final ConditionFactory INSTANCE = new CSSConditionFactory(); - - @Override - public AttributeCondition createClassCondition(String namespaceURI, String value) throws CSSException { - return new CSSClassCondition(null, "class", value); - } - - @Override - public AttributeCondition createAttributeCondition(String localName, String namespaceURI, boolean specified, - String value) throws CSSException { - return new CSSAttributeCondition(localName, namespaceURI, specified, value); - } - - @Override - public CombinatorCondition createAndCondition(Condition first, - Condition second) throws CSSException { - return new CSSAndCondition(first, second); - } - - @Override - public AttributeCondition createBeginHyphenAttributeCondition(String arg0, String arg1, boolean arg2, String arg3) - throws CSSException { - throw new CSSException("Not implemented in CSS2"); - } - - @Override - public ContentCondition createContentCondition(String arg0) throws CSSException { - throw new CSSException("Not implemented in CSS2"); - } - - @Override - public AttributeCondition createIdCondition(String arg0) throws CSSException { - throw new CSSException("Not implemented in CSS2"); - } - - @Override - public LangCondition createLangCondition(String arg0) throws CSSException { - throw new CSSException("Not implemented in CSS2"); - } - - @Override - public NegativeCondition createNegativeCondition(Condition arg0) throws CSSException { - throw new CSSException("Not implemented in CSS2"); - } - - @Override - public AttributeCondition createOneOfAttributeCondition(String arg0, String arg1, boolean arg2, String arg3) - throws CSSException { - throw new CSSException("Not implemented in CSS2"); - } - - @Override - public Condition createOnlyChildCondition() throws CSSException { - throw new CSSException("Not implemented in CSS2"); - } - - @Override - public Condition createOnlyTypeCondition() throws CSSException { - throw new CSSException("Not implemented in CSS2"); - } - - @Override - public CombinatorCondition createOrCondition(Condition arg0, Condition arg1) throws CSSException { - throw new CSSException("Not implemented in CSS2"); - } - - @Override - public PositionalCondition createPositionalCondition(int arg0, boolean arg1, boolean arg2) throws CSSException { - throw new CSSException("Not implemented in CSS2"); - } - - @Override - public AttributeCondition createPseudoClassCondition(String arg0, String arg1) throws CSSException { - throw new CSSException("Not implemented in CSS2"); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme.css; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.w3c.css.sac.AttributeCondition; +import org.w3c.css.sac.CSSException; +import org.w3c.css.sac.CombinatorCondition; +import org.w3c.css.sac.Condition; +import org.w3c.css.sac.ConditionFactory; +import org.w3c.css.sac.ContentCondition; +import org.w3c.css.sac.LangCondition; +import org.w3c.css.sac.NegativeCondition; +import org.w3c.css.sac.PositionalCondition; + +@NonNullByDefault({}) +public final class CSSConditionFactory implements ConditionFactory { + + public static final ConditionFactory INSTANCE = new CSSConditionFactory(); + + @Override + public AttributeCondition createClassCondition(final String namespaceURI, final String value) throws CSSException { + return new CSSClassCondition(null, "class", value); + } + + @Override + public AttributeCondition createAttributeCondition(final String localName, final String namespaceURI, + final boolean specified, final String value) throws CSSException { + return new CSSAttributeCondition(localName, namespaceURI, specified, value); + } + + @Override + public CombinatorCondition createAndCondition(final Condition first, final Condition second) throws CSSException { + return new CSSAndCondition(first, second); + } + + @Override + public AttributeCondition createBeginHyphenAttributeCondition(final String arg0, final String arg1, + final boolean arg2, final String arg3) throws CSSException { + throw new CSSException("Not implemented in CSS2"); + } + + @Override + public ContentCondition createContentCondition(final String arg0) throws CSSException { + throw new CSSException("Not implemented in CSS2"); + } + + @Override + public AttributeCondition createIdCondition(final String arg0) throws CSSException { + throw new CSSException("Not implemented in CSS2"); + } + + @Override + public LangCondition createLangCondition(final String arg0) throws CSSException { + throw new CSSException("Not implemented in CSS2"); + } + + @Override + public NegativeCondition createNegativeCondition(final Condition arg0) throws CSSException { + throw new CSSException("Not implemented in CSS2"); + } + + @Override + public AttributeCondition createOneOfAttributeCondition(final String arg0, final String arg1, final boolean arg2, + final String arg3) throws CSSException { + throw new CSSException("Not implemented in CSS2"); + } + + @Override + public Condition createOnlyChildCondition() throws CSSException { + throw new CSSException("Not implemented in CSS2"); + } + + @Override + public Condition createOnlyTypeCondition() throws CSSException { + throw new CSSException("Not implemented in CSS2"); + } + + @Override + public CombinatorCondition createOrCondition(final Condition arg0, final Condition arg1) throws CSSException { + throw new CSSException("Not implemented in CSS2"); + } + + @Override + public PositionalCondition createPositionalCondition(final int arg0, final boolean arg1, final boolean arg2) + throws CSSException { + throw new CSSException("Not implemented in CSS2"); + } + + @Override + public AttributeCondition createPseudoClassCondition(final String arg0, final String arg1) throws CSSException { + throw new CSSException("Not implemented in CSS2"); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSConditionalSelector.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSConditionalSelector.java similarity index 77% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSConditionalSelector.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSConditionalSelector.java index d632ea49a..43c12fa5a 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSConditionalSelector.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSConditionalSelector.java @@ -1,71 +1,71 @@ -/** - * Copyright (c) 2015-2018 Angelo ZERR. +/** + * Copyright (c) 2015-2018 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.css; - -import org.w3c.css.sac.Condition; -import org.w3c.css.sac.ConditionalSelector; -import org.w3c.css.sac.SimpleSelector; - -public class CSSConditionalSelector implements ConditionalSelector, ExtendedSelector { - - /** - * The simple selector. - */ - protected SimpleSelector simpleSelector; - - /** - * The condition. - */ - protected Condition condition; - - /** - * Creates a new ConditionalSelector object. - */ - public CSSConditionalSelector(SimpleSelector simpleSelector, Condition condition) { - this.simpleSelector = simpleSelector; - this.condition = condition; - } - - @Override - public short getSelectorType() { - return SAC_CONDITIONAL_SELECTOR; - } - - @Override - public Condition getCondition() { - return condition; - } - - @Override - public SimpleSelector getSimpleSelector() { - return simpleSelector; - } - - @Override - public int getSpecificity() { - return ((ExtendedSelector) getSimpleSelector()).getSpecificity() - + ((ExtendedCondition) getCondition()).getSpecificity(); - } - - @Override - public int nbMatch(String... names) { - return ((ExtendedSelector)getSimpleSelector()).nbMatch(names) + - ((ExtendedCondition)getCondition()).nbMatch(names); - } - - @Override - public int nbClass() { - return ((ExtendedSelector) getSimpleSelector()).nbClass() - + ((ExtendedCondition) getCondition()).nbClass(); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme.css; + +import org.w3c.css.sac.Condition; +import org.w3c.css.sac.ConditionalSelector; +import org.w3c.css.sac.SimpleSelector; + +final class CSSConditionalSelector implements ConditionalSelector, ExtendedSelector { + + /** + * The simple selector. + */ + private final SimpleSelector simpleSelector; + + /** + * The condition. + */ + private final Condition condition; + + /** + * Creates a new ConditionalSelector object. + */ + CSSConditionalSelector(final SimpleSelector simpleSelector, final Condition condition) { + this.simpleSelector = simpleSelector; + this.condition = condition; + } + + @Override + public short getSelectorType() { + return SAC_CONDITIONAL_SELECTOR; + } + + @Override + public Condition getCondition() { + return condition; + } + + @Override + public SimpleSelector getSimpleSelector() { + return simpleSelector; + } + + @Override + public int getSpecificity() { + return ((ExtendedSelector) getSimpleSelector()).getSpecificity() + + ((ExtendedCondition) getCondition()).getSpecificity(); + } + + @Override + public int nbMatch(final String... names) { + return ((ExtendedSelector)getSimpleSelector()).nbMatch(names) + + ((ExtendedCondition)getCondition()).nbMatch(names); + } + + @Override + public int nbClass() { + return ((ExtendedSelector) getSimpleSelector()).nbClass() + + ((ExtendedCondition) getCondition()).nbClass(); + } + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSDocumentHandler.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSDocumentHandler.java new file mode 100644 index 000000000..11bf0ed8a --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSDocumentHandler.java @@ -0,0 +1,149 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme.css; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.theme.IStyle; +import org.eclipse.tm4e.core.theme.RGB; +import org.w3c.css.sac.CSSException; +import org.w3c.css.sac.DocumentHandler; +import org.w3c.css.sac.InputSource; +import org.w3c.css.sac.LexicalUnit; +import org.w3c.css.sac.SACMediaList; +import org.w3c.css.sac.SelectorList; +import org.w3c.dom.css.CSSPrimitiveValue; + +public final class CSSDocumentHandler implements DocumentHandler { + + private final List list = new ArrayList<>(); + + @Nullable + private CSSStyle currentStyle; + + @Override + public void comment(@Nullable final String arg0) throws CSSException { + } + + @Override + public void endDocument(@Nullable final InputSource arg0) throws CSSException { + // TODO Auto-generated method stub + } + + @Override + public void endFontFace() throws CSSException { + // TODO Auto-generated method stub + } + + @Override + public void endMedia(@Nullable final SACMediaList arg0) throws CSSException { + // TODO Auto-generated method stub + } + + @Override + public void endPage(@Nullable final String arg0, @Nullable final String arg1) throws CSSException { + // TODO Auto-generated method stub + } + + @Override + public void endSelector(@Nullable final SelectorList selector) throws CSSException { + currentStyle = null; + } + + @Override + public void ignorableAtRule(@Nullable final String arg0) throws CSSException { + // TODO Auto-generated method stub + } + + @Override + public void importStyle(@Nullable final String arg0, @Nullable final SACMediaList arg1, @Nullable final String arg2) + throws CSSException { + // TODO Auto-generated method stub + } + + @Override + public void namespaceDeclaration(@Nullable final String arg0, @Nullable final String arg1) throws CSSException { + // TODO Auto-generated method stub + } + + @Override + public void property(@Nullable final String name, @Nullable final LexicalUnit value, final boolean arg2) + throws CSSException { + final var currentStyle = this.currentStyle; + if (currentStyle != null && name != null && value != null) { + switch (name) { + case "color": + currentStyle.setColor(createRGB(value)); + break; + case "background-color": + currentStyle.setBackgroundColor(createRGB(value)); + break; + case "font-weight": + currentStyle.setBold(value.getStringValue().toUpperCase().contains("BOLD")); + break; + case "font-style": + currentStyle.setItalic(value.getStringValue().toUpperCase().contains("ITALIC")); + break; + case "text-decoration": + final String decoration = value.getStringValue().toUpperCase(); + if (decoration.contains("UNDERLINE")) { + currentStyle.setUnderline(true); + } + if (decoration.contains("LINE-THROUGH")) { + currentStyle.setStrikeThrough(true); + } + break; + } + } + } + + private RGB createRGB(final LexicalUnit value) { + final var rgbColor = new RGBColorImpl(value); + final int green = ((int) rgbColor.getGreen().getFloatValue(CSSPrimitiveValue.CSS_NUMBER)); + final int red = ((int) rgbColor.getRed().getFloatValue(CSSPrimitiveValue.CSS_NUMBER)); + final int blue = ((int) rgbColor.getBlue().getFloatValue(CSSPrimitiveValue.CSS_NUMBER)); + return new RGB(red, green, blue); + } + + @Override + public void startDocument(@Nullable final InputSource arg0) throws CSSException { + // TODO Auto-generated method stub + } + + @Override + public void startFontFace() throws CSSException { + // TODO Auto-generated method stub + } + + @Override + public void startMedia(@Nullable final SACMediaList arg0) throws CSSException { + // TODO Auto-generated method stub + } + + @Override + public void startPage(@Nullable final String arg0, @Nullable final String arg1) throws CSSException { + // TODO Auto-generated method stub + } + + @Override + public void startSelector(@Nullable final SelectorList selector) throws CSSException { + assert selector != null; + currentStyle = new CSSStyle(selector); + list.add(currentStyle); + } + + public List getList() { + return list; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSElementSelector.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSElementSelector.java similarity index 69% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSElementSelector.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSElementSelector.java index ce42b0dc2..9943be8e5 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSElementSelector.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSElementSelector.java @@ -1,39 +1,41 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.css; - -public class CSSElementSelector extends AbstractElementSelector { - - public CSSElementSelector(String uri, String name) { - super(uri, name); - } - - @Override - public short getSelectorType() { - return SAC_ELEMENT_NODE_SELECTOR; - } - - @Override - public int getSpecificity() { - return (getLocalName() == null) ? 0 : 1; - } - - @Override - public int nbMatch(String... names) { - return 0; - } - - @Override - public int nbClass() { - return 0; - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme.css; + +import org.eclipse.jdt.annotation.Nullable; + +final class CSSElementSelector extends AbstractElementSelector { + + CSSElementSelector(@Nullable final String uri, @Nullable final String name) { + super(uri, name); + } + + @Override + public short getSelectorType() { + return SAC_ELEMENT_NODE_SELECTOR; + } + + @Override + public int getSpecificity() { + return (getLocalName() == null) ? 0 : 1; + } + + @Override + public int nbMatch(final String... names) { + return 0; + } + + @Override + public int nbClass() { + return 0; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSSelectorFactory.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSSelectorFactory.java similarity index 60% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSSelectorFactory.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSSelectorFactory.java index ae262994e..667a61db0 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSSelectorFactory.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSSelectorFactory.java @@ -1,100 +1,107 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - * Jochen Ulrich - exception messages - */ -package org.eclipse.tm4e.core.internal.css; - -import org.w3c.css.sac.CSSException; -import org.w3c.css.sac.CharacterDataSelector; -import org.w3c.css.sac.Condition; -import org.w3c.css.sac.ConditionalSelector; -import org.w3c.css.sac.DescendantSelector; -import org.w3c.css.sac.ElementSelector; -import org.w3c.css.sac.NegativeSelector; -import org.w3c.css.sac.ProcessingInstructionSelector; -import org.w3c.css.sac.Selector; -import org.w3c.css.sac.SelectorFactory; -import org.w3c.css.sac.SiblingSelector; -import org.w3c.css.sac.SimpleSelector; - -public class CSSSelectorFactory implements SelectorFactory { - - public static final SelectorFactory INSTANCE = new CSSSelectorFactory(); - - @Override - public SimpleSelector createAnyNodeSelector() throws CSSException { - throw new UnsupportedOperationException("CSS any selector is not supported"); - } - - @Override - public CharacterDataSelector createCDataSectionSelector(String arg0) throws CSSException { - throw new UnsupportedOperationException("CSS CDATA section is not supported"); - } - - @Override - public DescendantSelector createChildSelector(Selector arg0, SimpleSelector arg1) throws CSSException { - throw new UnsupportedOperationException("CSS child selector is not supported"); - } - - @Override - public CharacterDataSelector createCommentSelector(String arg0) throws CSSException { - throw new UnsupportedOperationException("CSS comment is not supported"); - } - - @Override - public ConditionalSelector createConditionalSelector(SimpleSelector selector, Condition condition) - throws CSSException { - return new CSSConditionalSelector(selector, condition); - } - - @Override - public DescendantSelector createDescendantSelector(Selector arg0, SimpleSelector arg1) throws CSSException { - throw new UnsupportedOperationException("CSS descendant selector is not supported"); - } - - @Override - public SiblingSelector createDirectAdjacentSelector(short arg0, Selector arg1, SimpleSelector arg2) - throws CSSException { - throw new UnsupportedOperationException("CSS direct adjacent selector is not supported"); - } - - @Override - public ElementSelector createElementSelector(String uri, String name) throws CSSException { - return new CSSElementSelector(uri, name); - } - - @Override - public NegativeSelector createNegativeSelector(SimpleSelector arg0) throws CSSException { - throw new UnsupportedOperationException("CSS negative selector is not supported"); - } - - @Override - public ProcessingInstructionSelector createProcessingInstructionSelector(String arg0, String arg1) - throws CSSException { - throw new UnsupportedOperationException("CSS processing instruction is not supported"); - } - - @Override - public ElementSelector createPseudoElementSelector(String arg0, String arg1) throws CSSException { - throw new UnsupportedOperationException("CSS pseudo element selector is not supported"); - } - - @Override - public SimpleSelector createRootNodeSelector() throws CSSException { - throw new UnsupportedOperationException("CSS root node selector is not supported"); - } - - @Override - public CharacterDataSelector createTextNodeSelector(String arg0) throws CSSException { - throw new UnsupportedOperationException("CSS text node selector is not supported"); - } - -} +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + * Jochen Ulrich - exception messages + */ +package org.eclipse.tm4e.core.internal.theme.css; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.w3c.css.sac.CSSException; +import org.w3c.css.sac.CharacterDataSelector; +import org.w3c.css.sac.Condition; +import org.w3c.css.sac.ConditionalSelector; +import org.w3c.css.sac.DescendantSelector; +import org.w3c.css.sac.ElementSelector; +import org.w3c.css.sac.NegativeSelector; +import org.w3c.css.sac.ProcessingInstructionSelector; +import org.w3c.css.sac.Selector; +import org.w3c.css.sac.SelectorFactory; +import org.w3c.css.sac.SiblingSelector; +import org.w3c.css.sac.SimpleSelector; + +@NonNullByDefault({}) +public final class CSSSelectorFactory implements SelectorFactory { + + public static final SelectorFactory INSTANCE = new CSSSelectorFactory(); + + @Override + public SimpleSelector createAnyNodeSelector() throws CSSException { + throw new UnsupportedOperationException("CSS any selector is not supported"); + } + + @Override + public CharacterDataSelector createCDataSectionSelector(final String arg0) throws CSSException { + throw new UnsupportedOperationException("CSS CDATA section is not supported"); + } + + @Override + public DescendantSelector createChildSelector(final Selector arg0, final SimpleSelector arg1) + throws CSSException { + throw new UnsupportedOperationException("CSS child selector is not supported"); + } + + @Override + public CharacterDataSelector createCommentSelector(final String arg0) throws CSSException { + throw new UnsupportedOperationException("CSS comment is not supported"); + } + + @Override + public ConditionalSelector createConditionalSelector(final SimpleSelector selector, final Condition condition) + throws CSSException { + return new CSSConditionalSelector(selector, condition); + } + + @Override + public DescendantSelector createDescendantSelector(final Selector arg0, + final SimpleSelector arg1) throws CSSException { + throw new UnsupportedOperationException("CSS descendant selector is not supported"); + } + + @Override + public SiblingSelector createDirectAdjacentSelector(final short arg0, final Selector arg1, + final SimpleSelector arg2) + throws CSSException { + throw new UnsupportedOperationException("CSS direct adjacent selector is not supported"); + } + + @Override + public ElementSelector createElementSelector(final String uri, final String name) throws CSSException { + return new CSSElementSelector(uri, name); + } + + @Override + public NegativeSelector createNegativeSelector(final SimpleSelector arg0) throws CSSException { + throw new UnsupportedOperationException("CSS negative selector is not supported"); + } + + @Override + public ProcessingInstructionSelector createProcessingInstructionSelector(final String arg0, + final String arg1) + throws CSSException { + throw new UnsupportedOperationException("CSS processing instruction is not supported"); + } + + @Override + public ElementSelector createPseudoElementSelector(final String arg0, final String arg1) + throws CSSException { + throw new UnsupportedOperationException("CSS pseudo element selector is not supported"); + } + + @Override + public SimpleSelector createRootNodeSelector() throws CSSException { + throw new UnsupportedOperationException("CSS root node selector is not supported"); + } + + @Override + public CharacterDataSelector createTextNodeSelector(final String arg0) throws CSSException { + throw new UnsupportedOperationException("CSS text node selector is not supported"); + } + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/CSSStyle.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSStyle.java similarity index 71% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/CSSStyle.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSStyle.java index 25e30d67d..8a246c3fb 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/CSSStyle.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSStyle.java @@ -1,91 +1,98 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.theme.css; - -import org.eclipse.tm4e.core.theme.IStyle; -import org.eclipse.tm4e.core.theme.RGB; -import org.w3c.css.sac.SelectorList; - -public class CSSStyle implements IStyle { - - private final SelectorList selector; - private RGB color; - private RGB backgroundColor; - - private boolean bold; - private boolean italic; - private boolean underline; - private boolean strikeThrough; - - public CSSStyle(SelectorList selector) { - this.selector = selector; - } - - public void setColor(RGB color) { - this.color = color; - } - - @Override - public RGB getColor() { - return color; - } - - @Override - public RGB getBackgroundColor() { - return backgroundColor; - } - - public void setBackgroundColor(RGB backgroundColor) { - this.backgroundColor = backgroundColor; - } - - public SelectorList getSelectorList() { - return selector; - } - - public void setBold(boolean bold) { - this.bold = bold; - } - - @Override - public boolean isBold() { - return bold; - } - - public void setItalic(boolean italic) { - this.italic = italic; - } - - @Override - public boolean isItalic() { - return italic; - } - - @Override - public boolean isUnderline() { - return underline; - } - - public void setUnderline(boolean underline) { - this.underline = underline; - } - - @Override - public boolean isStrikeThrough() { - return strikeThrough; - } - - public void setStrikeThrough(boolean strikeThrough) { - this.strikeThrough = strikeThrough; - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme.css; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.theme.IStyle; +import org.eclipse.tm4e.core.theme.RGB; +import org.w3c.css.sac.SelectorList; + +public class CSSStyle implements IStyle { + + private final SelectorList selector; + + @Nullable + private RGB color; + + @Nullable + private RGB backgroundColor; + + private boolean bold; + private boolean italic; + private boolean underline; + private boolean strikeThrough; + + public CSSStyle(final SelectorList selector) { + this.selector = selector; + } + + public void setColor(final RGB color) { + this.color = color; + } + + @Nullable + @Override + public RGB getColor() { + return color; + } + + @Nullable + @Override + public RGB getBackgroundColor() { + return backgroundColor; + } + + public void setBackgroundColor(final RGB backgroundColor) { + this.backgroundColor = backgroundColor; + } + + public SelectorList getSelectorList() { + return selector; + } + + public void setBold(final boolean bold) { + this.bold = bold; + } + + @Override + public boolean isBold() { + return bold; + } + + public void setItalic(final boolean italic) { + this.italic = italic; + } + + @Override + public boolean isItalic() { + return italic; + } + + @Override + public boolean isUnderline() { + return underline; + } + + public void setUnderline(final boolean underline) { + this.underline = underline; + } + + @Override + public boolean isStrikeThrough() { + return strikeThrough; + } + + public void setStrikeThrough(final boolean strikeThrough) { + this.strikeThrough = strikeThrough; + } + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSValueImpl.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSValueImpl.java similarity index 59% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSValueImpl.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSValueImpl.java index e085f8bf6..857435437 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/CSSValueImpl.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/CSSValueImpl.java @@ -1,131 +1,91 @@ -/******************************************************************************* - * Copyright (c) 2008, 2013 Angelo Zerr and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Angelo Zerr - initial API and implementation - * IBM Corporation - ongoing development - *******************************************************************************/ -package org.eclipse.tm4e.core.internal.css; - -import org.w3c.dom.DOMException; -import org.w3c.dom.css.CSSPrimitiveValue; -import org.w3c.dom.css.CSSValue; -import org.w3c.dom.css.Counter; -import org.w3c.dom.css.RGBColor; -import org.w3c.dom.css.Rect; - -public abstract class CSSValueImpl implements CSSPrimitiveValue, CSSValue { - - // W3C CSSValue API methods - - /* - * (non-Javadoc) - * - * @see org.w3c.dom.css.CSSValue#getCssText() - */ - public String getCssText() { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); - } - - /* - * (non-Javadoc) - * - * @see org.w3c.dom.css.CSSValue#getCssValueType() - */ - public short getCssValueType() { - return CSS_PRIMITIVE_VALUE; - } - - /* - * (non-Javadoc) - * - * @see org.w3c.dom.css.CSSValue#setCssText(java.lang.String) - */ - public void setCssText(String cssText) throws DOMException { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); - } - - // W3C CSSPrimitiveValue API methods - - /* - * (non-Javadoc) - * - * @see org.w3c.dom.css.CSSPrimitiveValue#getPrimitiveType() - */ - public short getPrimitiveType() { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); - } - - /* - * (non-Javadoc) - * - * @see org.w3c.dom.css.CSSPrimitiveValue#getCounterValue() - */ - public Counter getCounterValue() throws DOMException { - throw new DOMException(DOMException.INVALID_ACCESS_ERR, "COUNTER_ERROR"); - } - - /* - * (non-Javadoc) - * - * @see org.w3c.dom.css.CSSPrimitiveValue#getRGBColorValue() - */ - public RGBColor getRGBColorValue() throws DOMException { - throw new DOMException(DOMException.INVALID_ACCESS_ERR, "RGBCOLOR_ERROR"); - } - - /* - * (non-Javadoc) - * - * @see org.w3c.dom.css.CSSPrimitiveValue#getRectValue() - */ - public Rect getRectValue() throws DOMException { - throw new DOMException(DOMException.INVALID_ACCESS_ERR, "RECT_ERROR"); - } - - /* - * (non-Javadoc) - * - * @see org.w3c.dom.css.CSSPrimitiveValue#getStringValue() - */ - public String getStringValue() throws DOMException { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); - } - - /* - * (non-Javadoc) - * - * @see org.w3c.dom.css.CSSPrimitiveValue#setFloatValue(short, float) - */ - public void setFloatValue(short arg0, float arg1) throws DOMException { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); - } - - /* - * (non-Javadoc) - * - * @see org.w3c.dom.css.CSSPrimitiveValue#setStringValue(short, - * java.lang.String) - */ - public void setStringValue(short arg0, String arg1) throws DOMException { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); - } - - // Additional methods - - public float getFloatValue(short valueType) throws DOMException { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); - } - +/******************************************************************************* + * Copyright (c) 2008, 2013 Angelo Zerr and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + * IBM Corporation - ongoing development + *******************************************************************************/ +package org.eclipse.tm4e.core.internal.theme.css; + +import org.eclipse.jdt.annotation.Nullable; +import org.w3c.dom.DOMException; +import org.w3c.dom.css.CSSPrimitiveValue; +import org.w3c.dom.css.Counter; +import org.w3c.dom.css.RGBColor; +import org.w3c.dom.css.Rect; + +abstract class CSSValueImpl implements CSSPrimitiveValue { + + // W3C CSSValue API methods + + @Override + public String getCssText() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); + } + + @Override + public short getCssValueType() { + return CSS_PRIMITIVE_VALUE; + } + + @Override + public void setCssText(@Nullable final String cssText) throws DOMException { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); + } + + // W3C CSSPrimitiveValue API methods + + @Override + public short getPrimitiveType() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); + } + + @Override + public Counter getCounterValue() throws DOMException { + throw new DOMException(DOMException.INVALID_ACCESS_ERR, "COUNTER_ERROR"); + } + + @Override + public RGBColor getRGBColorValue() throws DOMException { + throw new DOMException(DOMException.INVALID_ACCESS_ERR, "RGBCOLOR_ERROR"); + } + + @Override + public Rect getRectValue() throws DOMException { + throw new DOMException(DOMException.INVALID_ACCESS_ERR, "RECT_ERROR"); + } + + @Override + public String getStringValue() throws DOMException { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); + } + + @Override + public void setFloatValue(final short arg0, final float arg1) throws DOMException { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); + } + + @Override + public void setStringValue(final short arg0, @Nullable final String arg1) throws DOMException { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); + } + + // Additional methods + + @Override + public float getFloatValue(final short valueType) throws DOMException { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); + } + } \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/ExtendedCondition.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/ExtendedCondition.java similarity index 83% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/ExtendedCondition.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/ExtendedCondition.java index 4dffc1623..a20c5a171 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/ExtendedCondition.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/ExtendedCondition.java @@ -1,24 +1,24 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.css; - -public interface ExtendedCondition { - - /** - * Returns the specificity of this condition. - */ - int getSpecificity(); - - int nbClass(); - - int nbMatch(String... names); -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme.css; + +interface ExtendedCondition { + + /** + * Returns the specificity of this condition. + */ + int getSpecificity(); + + int nbClass(); + + int nbMatch(String... names); +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/ExtendedSelector.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/ExtendedSelector.java similarity index 89% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/ExtendedSelector.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/ExtendedSelector.java index cbb182064..541047cdd 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/ExtendedSelector.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/ExtendedSelector.java @@ -1,26 +1,26 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.css; - -import org.w3c.css.sac.Selector; - -public interface ExtendedSelector extends Selector { - - /** - * Returns the specificity of this selector. - */ - int getSpecificity(); - - int nbMatch(String... names); - - int nbClass(); -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.theme.css; + +import org.w3c.css.sac.Selector; + +public interface ExtendedSelector extends Selector { + + /** + * Returns the specificity of this selector. + */ + int getSpecificity(); + + int nbMatch(String... names); + + int nbClass(); +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/Measure.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/Measure.java similarity index 75% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/Measure.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/Measure.java index 4ca24ad7f..424e5e55e 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/Measure.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/Measure.java @@ -1,148 +1,124 @@ -/******************************************************************************* - * Copyright (c) 2008, 2013 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ - -package org.eclipse.tm4e.core.internal.css; - -import org.w3c.css.sac.LexicalUnit; -import org.w3c.dom.DOMException; -import org.w3c.dom.css.CSSValue; - -public class Measure extends CSSValueImpl { - - LexicalUnit value; - - public Measure(LexicalUnit value) { - super(); - this.value = value; - } - - /** - * Return a float representation of the receiver's value. - * - * @param valueType - * a short representing the value type, see - * {@link CSSValue#getCssValueType()} - */ - public float getFloatValue(short valueType) throws DOMException { - // If it's actually a SAC_INTEGER return the integer value, callers tend - // to expect and cast - // There is no getIntegerFloat(short) - // TODO Not sure the purpose of arg valyeType, its not referenced in - // this method - if (value.getLexicalUnitType() == LexicalUnit.SAC_INTEGER) - return value.getIntegerValue(); - // TODO not sure what to do if it's not one of the lexical unit types - // that are specified in LexicalUnit#getFloatValue() - // ie. SAC_DEGREE, SAC_GRADIAN, SAC_RADIAN, SAC_MILLISECOND, SAC_SECOND, - // SAC_HERTZ or SAC_KILOHERTZ - return value.getFloatValue(); - } - - /** - * Return an int representation of the receiver's value. - * - * @param valueType - * a short representing the value type, see - * {@link CSSValue#getCssValueType()} - */ - public int getIntegerValue(short valueType) throws DOMException { - return value.getIntegerValue(); - } - - /* - * (non-Javadoc) - * - * @see org.w3c.dom.css.CSSPrimitiveValue#getStringValue() - */ - public String getStringValue() throws DOMException { - short lexicalUnit = value.getLexicalUnitType(); - if ((lexicalUnit == LexicalUnit.SAC_IDENT) || (lexicalUnit == LexicalUnit.SAC_STRING_VALUE) - || (lexicalUnit == LexicalUnit.SAC_URI)) - return value.getStringValue(); - // TODO There are more cases to catch of getLexicalUnitType() - throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); - } - - /* - * (non-Javadoc) - * - * @see org.w3c.dom.css.CSSPrimitiveValue#getPrimitiveType() - */ - public short getPrimitiveType() { - switch (value.getLexicalUnitType()) { - case LexicalUnit.SAC_IDENT: - return CSS_IDENT; - case LexicalUnit.SAC_INTEGER: - case LexicalUnit.SAC_REAL: - return CSS_NUMBER; - case LexicalUnit.SAC_URI: - return CSS_URI; - case LexicalUnit.SAC_PERCENTAGE: - return CSS_PERCENTAGE; - case LexicalUnit.SAC_PIXEL: - return CSS_PX; - case LexicalUnit.SAC_CENTIMETER: - return CSS_CM; - case LexicalUnit.SAC_EM: - return CSS_EMS; - case LexicalUnit.SAC_EX: - return CSS_EXS; - case LexicalUnit.SAC_INCH: - return CSS_IN; - case LexicalUnit.SAC_STRING_VALUE: - return CSS_STRING; - case LexicalUnit.SAC_DIMENSION: - return CSS_DIMENSION; - case LexicalUnit.SAC_OPERATOR_COMMA: - return CSS_CUSTOM; // TODO don't think this is right, see bug - // #278139 - case LexicalUnit.SAC_INHERIT: - return CSS_INHERIT; - } - // TODO Auto-generated method stub - throw new UnsupportedOperationException( - "NOT YET IMPLEMENTED - LexicalUnit type: " + value.getLexicalUnitType()); - } - - /* - * (non-Javadoc) - * - * @see org.w3c.dom.css.CSSValue#getCssText() - */ - public String getCssText() { - // TODO: All LexicalUnit.SAC_OPERATOR_* except for COMMA left undone for - // now as it's not even clear whether they should be treated as measures - // see bug #278139 - switch (value.getLexicalUnitType()) { - case LexicalUnit.SAC_INTEGER: - return String.valueOf(value.getIntegerValue()); - case LexicalUnit.SAC_REAL: - return String.valueOf(value.getFloatValue()); - case LexicalUnit.SAC_PERCENTAGE: - case LexicalUnit.SAC_PIXEL: - case LexicalUnit.SAC_CENTIMETER: - case LexicalUnit.SAC_EM: - case LexicalUnit.SAC_EX: - case LexicalUnit.SAC_PICA: - case LexicalUnit.SAC_POINT: - case LexicalUnit.SAC_INCH: - case LexicalUnit.SAC_DEGREE: - return String.valueOf(value.getFloatValue()) + value.getDimensionUnitText(); - case LexicalUnit.SAC_URI: - return "url(" + value.getStringValue() + ")"; - case LexicalUnit.SAC_OPERATOR_COMMA: - return ","; - case LexicalUnit.SAC_INHERIT: - return "inherit"; - } - return value.getStringValue(); - } +/******************************************************************************* + * Copyright (c) 2008, 2013 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm4e.core.internal.theme.css; + +import org.w3c.css.sac.LexicalUnit; +import org.w3c.dom.DOMException; +import org.w3c.dom.css.CSSValue; + +final class Measure extends CSSValueImpl { + + private final LexicalUnit value; + + Measure(final LexicalUnit value) { + this.value = value; + } + + /** + * Return a float representation of the receiver's value. + * + * @param valueType + * a short representing the value type, see + * {@link CSSValue#getCssValueType()} + */ + @Override + public float getFloatValue(final short valueType) throws DOMException { + // If it's actually a SAC_INTEGER return the integer value, callers tend + // to expect and cast + // There is no getIntegerFloat(short) + // TODO Not sure the purpose of arg valyeType, its not referenced in + // this method + if (value.getLexicalUnitType() == LexicalUnit.SAC_INTEGER) + return value.getIntegerValue(); + // TODO not sure what to do if it's not one of the lexical unit types + // that are specified in LexicalUnit#getFloatValue() + // ie. SAC_DEGREE, SAC_GRADIAN, SAC_RADIAN, SAC_MILLISECOND, SAC_SECOND, + // SAC_HERTZ or SAC_KILOHERTZ + return value.getFloatValue(); + } + + @Override + public String getStringValue() throws DOMException { + final short lexicalUnit = value.getLexicalUnitType(); + if ((lexicalUnit == LexicalUnit.SAC_IDENT) || (lexicalUnit == LexicalUnit.SAC_STRING_VALUE) + || (lexicalUnit == LexicalUnit.SAC_URI)) + return value.getStringValue(); + // TODO There are more cases to catch of getLexicalUnitType() + throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); + } + + @Override + public short getPrimitiveType() { + switch (value.getLexicalUnitType()) { + case LexicalUnit.SAC_IDENT: + return CSS_IDENT; + case LexicalUnit.SAC_INTEGER: + case LexicalUnit.SAC_REAL: + return CSS_NUMBER; + case LexicalUnit.SAC_URI: + return CSS_URI; + case LexicalUnit.SAC_PERCENTAGE: + return CSS_PERCENTAGE; + case LexicalUnit.SAC_PIXEL: + return CSS_PX; + case LexicalUnit.SAC_CENTIMETER: + return CSS_CM; + case LexicalUnit.SAC_EM: + return CSS_EMS; + case LexicalUnit.SAC_EX: + return CSS_EXS; + case LexicalUnit.SAC_INCH: + return CSS_IN; + case LexicalUnit.SAC_STRING_VALUE: + return CSS_STRING; + case LexicalUnit.SAC_DIMENSION: + return CSS_DIMENSION; + case LexicalUnit.SAC_OPERATOR_COMMA: + return CSS_CUSTOM; // TODO don't think this is right, see bug #278139 + case LexicalUnit.SAC_INHERIT: + return CSS_INHERIT; + default: + // TODO Auto-generated method stub + throw new UnsupportedOperationException( + "NOT YET IMPLEMENTED - LexicalUnit type: " + value.getLexicalUnitType()); + } + } + + @Override + public String getCssText() { + // TODO: All LexicalUnit.SAC_OPERATOR_* except for COMMA left undone for + // now as it's not even clear whether they should be treated as measures + // see bug #278139 + switch (value.getLexicalUnitType()) { + case LexicalUnit.SAC_INTEGER: + return String.valueOf(value.getIntegerValue()); + case LexicalUnit.SAC_REAL: + return String.valueOf(value.getFloatValue()); + case LexicalUnit.SAC_PERCENTAGE: + case LexicalUnit.SAC_PIXEL: + case LexicalUnit.SAC_CENTIMETER: + case LexicalUnit.SAC_EM: + case LexicalUnit.SAC_EX: + case LexicalUnit.SAC_PICA: + case LexicalUnit.SAC_POINT: + case LexicalUnit.SAC_INCH: + case LexicalUnit.SAC_DEGREE: + return String.valueOf(value.getFloatValue()) + value.getDimensionUnitText(); + case LexicalUnit.SAC_URI: + return "url(" + value.getStringValue() + ")"; + case LexicalUnit.SAC_OPERATOR_COMMA: + return ","; + case LexicalUnit.SAC_INHERIT: + return "inherit"; + } + return value.getStringValue(); + } } \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/RGBColorImpl.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/RGBColorImpl.java similarity index 65% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/RGBColorImpl.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/RGBColorImpl.java index 636c46d03..f3e920c4f 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/RGBColorImpl.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/RGBColorImpl.java @@ -1,82 +1,64 @@ -/******************************************************************************* - * Copyright (c) 2008, 2013 Angelo Zerr and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Angelo Zerr - initial API and implementation - * IBM Corporation - ongoing development - *******************************************************************************/ -package org.eclipse.tm4e.core.internal.css; - -import org.w3c.css.sac.LexicalUnit; -import org.w3c.dom.DOMException; -import org.w3c.dom.css.CSSPrimitiveValue; -import org.w3c.dom.css.RGBColor; - -public class RGBColorImpl extends CSSValueImpl implements RGBColor { - - private CSSPrimitiveValue red; - private CSSPrimitiveValue green; - private CSSPrimitiveValue blue; - - public RGBColorImpl(LexicalUnit lexicalUnit) { - LexicalUnit nextUnit = lexicalUnit.getParameters(); - red = new Measure(nextUnit); - nextUnit = nextUnit.getNextLexicalUnit().getNextLexicalUnit(); - green = new Measure(nextUnit); - nextUnit = nextUnit.getNextLexicalUnit().getNextLexicalUnit(); - blue = new Measure(nextUnit); - } - - /* - * (non-Javadoc) - * @see org.w3c.dom.css.RGBColor#getRed() - */ - public CSSPrimitiveValue getRed() { - return red; - } - - /* - * (non-Javadoc) - * @see org.w3c.dom.css.RGBColor#getGreen() - */ - public CSSPrimitiveValue getGreen() { - return green; - } - - /* - * (non-Javadoc) - * @see org.w3c.dom.css.RGBColor#getBlue() - */ - public CSSPrimitiveValue getBlue() { - return blue; - } - - /* - * (non-Javadoc) - * @see org.w3c.dom.css.CSSValue#getRGBColorValue() - */ - public RGBColor getRGBColorValue() throws DOMException { - return this; - } - - /* - * (non-Javadoc) - * @see org.w3c.dom.css.CSSValue#getPrimitiveType() - */ - public short getPrimitiveType() { - return CSS_RGBCOLOR; - } - - /* - * (non-Javadoc) - * @see org.w3c.dom.css.CSSValue#getCssText() - */ - public String getCssText() { - return "rgb(" + red.getCssText() + ", " + green.getCssText() + ", " - + blue.getCssText() + ")"; - } +/******************************************************************************* + * Copyright (c) 2008, 2013 Angelo Zerr and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + * IBM Corporation - ongoing development + *******************************************************************************/ +package org.eclipse.tm4e.core.internal.theme.css; + +import org.w3c.css.sac.LexicalUnit; +import org.w3c.dom.DOMException; +import org.w3c.dom.css.CSSPrimitiveValue; +import org.w3c.dom.css.RGBColor; + +final class RGBColorImpl extends CSSValueImpl implements RGBColor { + + private final CSSPrimitiveValue red; + private final CSSPrimitiveValue green; + private final CSSPrimitiveValue blue; + + RGBColorImpl(final LexicalUnit lexicalUnit) { + LexicalUnit nextUnit = lexicalUnit.getParameters(); + red = new Measure(nextUnit); + nextUnit = nextUnit.getNextLexicalUnit().getNextLexicalUnit(); + green = new Measure(nextUnit); + nextUnit = nextUnit.getNextLexicalUnit().getNextLexicalUnit(); + blue = new Measure(nextUnit); + } + + @Override + public CSSPrimitiveValue getRed() { + return red; + } + + @Override + public CSSPrimitiveValue getGreen() { + return green; + } + + @Override + public CSSPrimitiveValue getBlue() { + return blue; + } + + @Override + public RGBColor getRGBColorValue() throws DOMException { + return this; + } + + @Override + public short getPrimitiveType() { + return CSS_RGBCOLOR; + } + + @Override + public String getCssText() { + return "rgb(" + red.getCssText() + ", " + green.getCssText() + ", " + + blue.getCssText() + ")"; + } } \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/package-info.java new file mode 100644 index 000000000..f2ef4ad38 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.core.internal.theme.css; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/sac/AbstractSACParserFactory.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/sac/AbstractSACParserFactory.java new file mode 100644 index 000000000..0911ab0fa --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/sac/AbstractSACParserFactory.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2008, 2014 Angelo Zerr and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm4e.core.internal.theme.css.sac; + +import static java.lang.System.Logger.Level.*; + +import java.lang.System.Logger; + +import org.eclipse.jdt.annotation.Nullable; +import org.w3c.css.sac.Parser; +import org.w3c.css.sac.helpers.ParserFactory; + +/** + * SAC Parser Factory. + */ +public abstract class AbstractSACParserFactory extends ParserFactory implements ISACParserFactory { + + private static final Logger LOGGER = System.getLogger(AbstractSACParserFactory.class.getName()); + + @Nullable + private String preferredParserName; + + /** + * Return default instance of SAC Parser. If preferredParserName is filled, + * it return the instance of SAC Parser registered with this name, otherwise + * this method search the SAC Parser class name to instantiate into System + * property with key org.w3c.css.sac.parser. + */ + @Override + public Parser makeParser() throws ClassNotFoundException, IllegalAccessException, InstantiationException, + NullPointerException, ClassCastException { + try { + if (preferredParserName != null) { + return makeParser(preferredParserName); + } + } catch (final Throwable ex) { + LOGGER.log(ERROR, ex.getMessage(), ex); + } + return super.makeParser(); + } + + @Nullable + @Override + public String getPreferredParserName() { + return preferredParserName; + } + + @Override + public void setPreferredParserName(@Nullable final String preferredParserName) { + this.preferredParserName = preferredParserName; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/sac/ISACParserFactory.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/sac/ISACParserFactory.java new file mode 100644 index 000000000..09f056e2d --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/sac/ISACParserFactory.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2008, 2013 Angelo Zerr and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Angelo Zerr - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm4e.core.internal.theme.css.sac; + +import org.eclipse.jdt.annotation.Nullable; +import org.w3c.css.sac.Parser; + +/** + * SAC parser factory interface to get instance of SAC {@link Parser}. + */ +public interface ISACParserFactory { + + /** + * Return preferred SAC parser name if it is filled and null otherwise. + */ + @Nullable + String getPreferredParserName(); + + /** + * Set the preferred SAC parser name to use when makeParser is called. + * + * @param preferredParserName + */ + void setPreferredParserName(@Nullable final String preferredParserName); + + /** + * Return default instance of SAC Parser. + * + * If preferredParserName is filled, it return the instance of SAC Parser registered with this name, + * otherwise this method search the SAC Parser class name to instantiate into System property with key + * org.w3c.css.sac.parser. + */ + Parser makeParser() + throws ClassNotFoundException, IllegalAccessException, InstantiationException, ClassCastException; + + /** + * Return instance of SAC Parser registered into the factory with name name. + * + * @param name + * @see SACConstants + */ + Parser makeParser(String name) + throws ClassNotFoundException, IllegalAccessException, InstantiationException, ClassCastException; +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/SACConstants.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/sac/SACConstants.java similarity index 91% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/SACConstants.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/sac/SACConstants.java index 5be9139be..3c901cb4c 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/SACConstants.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/sac/SACConstants.java @@ -8,7 +8,7 @@ * Contributors: * Angelo Zerr - initial API and implementation *******************************************************************************/ -package org.eclipse.tm4e.core.theme.css; +package org.eclipse.tm4e.core.internal.theme.css.sac; /** * SAC Constants Parsers. @@ -17,7 +17,7 @@ * @author Angelo ZERR * */ -public class SACConstants { +public final class SACConstants { /** * org.w3c.flute.parser.Parser SAC Parser. @@ -39,4 +39,6 @@ public class SACConstants { */ public static final String SACPARSER_BATIK = "org.apache.batik.css.parser.Parser"; + private SACConstants() { + } } diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/SACParserFactoryImpl.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/sac/SACParserFactory.java similarity index 54% rename from org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/SACParserFactoryImpl.java rename to org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/sac/SACParserFactory.java index 72e4b301b..eabb24f6c 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/css/SACParserFactoryImpl.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/css/sac/SACParserFactory.java @@ -6,24 +6,24 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Angelo Zerr - initial API and implementation + * Angelo Zerr - initial API and implementation *******************************************************************************/ -package org.eclipse.tm4e.core.internal.css; +package org.eclipse.tm4e.core.internal.theme.css.sac; +import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map; -import org.eclipse.tm4e.core.theme.css.SACConstants; -import org.eclipse.tm4e.core.theme.css.SACParserFactory; +import org.eclipse.jdt.annotation.Nullable; import org.w3c.css.sac.Parser; /** * SAC Parser factory implementation. By default, this SAC FActory support * Flute, SteadyState and Batik SAC Parser. */ -public class SACParserFactoryImpl extends SACParserFactory { +public final class SACParserFactory extends AbstractSACParserFactory { - private static Map parsers = new HashMap<>(); + private static Map parsers = new HashMap<>(); static { // Register Flute SAC Parser @@ -36,21 +36,27 @@ public class SACParserFactoryImpl extends SACParserFactory { registerSACParser(SACConstants.SACPARSER_BATIK); } - public SACParserFactoryImpl() { + public SACParserFactory() { // Flute parser is the default SAC Parser to use. super.setPreferredParserName(SACConstants.SACPARSER_BATIK); } @Override - public Parser makeParser(String name) throws ClassNotFoundException, IllegalAccessException, InstantiationException, - NullPointerException, ClassCastException { - String classNameParser = parsers.get(name); + public Parser makeParser(final String name) throws ClassNotFoundException, IllegalAccessException, + InstantiationException, ClassCastException { + final String classNameParser = parsers.get(name); if (classNameParser != null) { - Class classParser = super.getClass().getClassLoader().loadClass(classNameParser); - return (Parser) classParser.newInstance(); + final Class classParser = super.getClass().getClassLoader().loadClass(classNameParser); + try { + final var parser = (Parser) classParser.getDeclaredConstructor().newInstance(); + assert parser != null; + return parser; + } catch (InvocationTargetException | NoSuchMethodException ex) { + throw (InstantiationException) ((new InstantiationException()).initCause(ex)); + } } - throw new IllegalAccessException("SAC parser with name=" + name - + " was not registered into SAC parser factory."); + throw new IllegalAccessException( + "SAC parser with name=" + name + " was not registered into SAC parser factory."); } /** @@ -58,7 +64,7 @@ public Parser makeParser(String name) throws ClassNotFoundException, IllegalAcce * * @param parser */ - public static void registerSACParser(String parser) { + private static void registerSACParser(final String parser) { registerSACParser(parser, parser); } @@ -69,7 +75,7 @@ public static void registerSACParser(String parser) { * @param name * @param classNameParser */ - public static void registerSACParser(String name, String classNameParser) { + private static void registerSACParser(final String name, final String classNameParser) { parsers.put(name, classNameParser); } } diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/package-info.java new file mode 100644 index 000000000..869577ab7 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.core.internal.theme; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/reader/IThemeParser.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/reader/IThemeParser.java deleted file mode 100644 index a5701b1fe..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/reader/IThemeParser.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/Microsoft/vscode-textmate/ - * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. - * Initial license: MIT - * - * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.theme.reader; - -import java.io.InputStream; - -import org.eclipse.tm4e.core.theme.IRawTheme; - -/** - * TextMate Theme parser. - * - */ -@FunctionalInterface -public interface IThemeParser { - - IRawTheme parse(InputStream contents) throws Exception; -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/reader/SyncThemeReader.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/reader/SyncThemeReader.java index 8e4b14641..ecd1a1127 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/reader/SyncThemeReader.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/reader/SyncThemeReader.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,26 +11,27 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java */ package org.eclipse.tm4e.core.internal.theme.reader; import java.io.InputStream; -import org.eclipse.tm4e.core.theme.IRawTheme; +import org.eclipse.tm4e.core.internal.parser.PListParser; +import org.eclipse.tm4e.core.internal.theme.IRawTheme; -public class SyncThemeReader { +final class SyncThemeReader { private final InputStream in; - private final IThemeParser parser; + private final PListParser parser; - SyncThemeReader(InputStream in, IThemeParser parser) { + SyncThemeReader(final InputStream in, final PListParser parser) { this.in = in; this.parser = parser; } - public IRawTheme load() throws Exception { + IRawTheme load() throws Exception { return this.parser.parse(in); } } diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/reader/ThemeReader.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/reader/ThemeReader.java index 5742efd95..a86843605 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/reader/ThemeReader.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/reader/ThemeReader.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,58 +11,59 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java */ package org.eclipse.tm4e.core.internal.theme.reader; import java.io.InputStream; -import org.eclipse.tm4e.core.internal.parser.json.JSONPListParser; -import org.eclipse.tm4e.core.internal.parser.xml.XMLPListParser; -import org.eclipse.tm4e.core.theme.IRawTheme; +import org.eclipse.tm4e.core.internal.parser.PListPath; +import org.eclipse.tm4e.core.internal.parser.PropertySettable; +import org.eclipse.tm4e.core.internal.parser.PListParser; +import org.eclipse.tm4e.core.internal.parser.PListParserJSON; +import org.eclipse.tm4e.core.internal.parser.PListParserXML; +import org.eclipse.tm4e.core.internal.parser.PListParserYAML; +import org.eclipse.tm4e.core.internal.theme.IRawTheme; +import org.eclipse.tm4e.core.internal.theme.ThemeRaw; /** * TextMate Theme reader utilities. * */ -public class ThemeReader { +public final class ThemeReader { - /** - * Helper class, use methods statically - */ - private ThemeReader() { - } + private static final PropertySettable.Factory OBJECT_FACTORY = path -> new ThemeRaw(); - public static final IThemeParser XML_PARSER = new IThemeParser() { + private static final PListParserJSON JSON_PARSER = new PListParserJSON<>(OBJECT_FACTORY); + private static final PListParserYAML YAML_PARSER = new PListParserYAML<>(OBJECT_FACTORY); + private static final PListParserXML XML_PARSER = new PListParserXML<>(OBJECT_FACTORY); - private final XMLPListParser parser = new XMLPListParser<>(true); + public static IRawTheme readThemeSync(final String filePath, final InputStream in) throws Exception { + final var reader = new SyncThemeReader(in, getThemeParser(filePath)); + return reader.load(); + } - @Override - public IRawTheme parse(InputStream contents) throws Exception { - return parser.parse(contents); - } - }; + private static PListParser getThemeParser(final String filePath) { + final String extension = filePath.substring(filePath.lastIndexOf('.') + 1).trim().toLowerCase(); + + switch (extension) { - public static final IThemeParser JSON_PARSER = new IThemeParser() { + case "json": + return JSON_PARSER; - private final JSONPListParser parser = new JSONPListParser<>(true); + case "yaml": + case "yml": + return YAML_PARSER; - @Override - public IRawTheme parse(InputStream contents) throws Exception { - return parser.parse(contents); + default: + return XML_PARSER; } - }; - - public static IRawTheme readThemeSync(String filePath, InputStream in) throws Exception { - SyncThemeReader reader = new SyncThemeReader(in, getThemeParser(filePath)); - return reader.load(); } - private static IThemeParser getThemeParser(String filePath) { - if (filePath.endsWith(".json")) { - return JSON_PARSER; - } - return XML_PARSER; + /** + * Helper class, use methods statically + */ + private ThemeReader() { } } diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/reader/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/reader/package-info.java new file mode 100644 index 000000000..8f8b39774 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/theme/reader/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.core.internal.theme.reader; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IBaseRaw.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IBaseRaw.java deleted file mode 100644 index c90f34e42..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IBaseRaw.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Initial code from https://github.com/Microsoft/vscode-textmate/ - * Initial copyright Copyright (C) Microsoft Corporation. All rights reserved. - * Initial license: MIT - * - * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.types; - -public interface IBaseRaw extends Iterable{ - -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IRawCaptures.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IRawCaptures.java index afc34e170..25e0a6ec9 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IRawCaptures.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IRawCaptures.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,13 +11,14 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.types; - -public interface IRawCaptures extends IBaseRaw { - - IRawRule getCapture(String captureId); - -} + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.types; + +public interface IRawCaptures { + + IRawRule getCapture(String captureId); + + Iterable getCaptureIds(); +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IRawGrammar.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IRawGrammar.java index 80b6d5f1d..6a884c9c5 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IRawGrammar.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IRawGrammar.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,31 +11,49 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.types; - -import java.util.Collection; -import java.util.Map; - -public interface IRawGrammar { - - IRawRepository getRepository(); - - String getScopeName(); - - Collection getPatterns(); - - Map getInjections(); - - String getInjectionSelector(); - - // injections?:{ [expression:string]: IRawRule }; - - Collection getFileTypes(); - - String getName(); - - String getFirstLineMatch(); -} + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.types; + +import java.util.Collection; +import java.util.Map; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/rawGrammar.ts + */ +public interface IRawGrammar { + + IRawGrammar deepClone(); + + boolean isRepositorySet(); + IRawRepository getRepository(); + + String getScopeName(); + + @Nullable // TODO non-null in upstream project + Collection getPatterns(); + + @Nullable + Map getInjections(); + + @Nullable + String getInjectionSelector(); + + Collection getFileTypes(); + + @Nullable + String getName(); + + @Nullable + String getFirstLineMatch(); + + void setRepository(IRawRepository repository); + + IRawRule toRawRule(); + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IRawRepository.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IRawRepository.java index e763f115c..43d9905fe 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IRawRepository.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IRawRepository.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,23 +11,37 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.types; - -public interface IRawRepository { - - // IRawRule getRule(String name); - - IRawRule getProp(String name); - - IRawRule getBase(); - - IRawRule getSelf(); - - void setSelf(IRawRule raw); - - void setBase(IRawRule base); - -} + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.types; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.grammar.RawRepository; +import org.eclipse.tm4e.core.internal.parser.PropertySettable; + +public interface IRawRepository { + + static IRawRepository merge(@Nullable final IRawRepository... sources) { + final RawRepository merged = new RawRepository(); + for (final var source : sources) { + if (source == null) + continue; + source.putEntries(merged); + } + return merged; + } + + void putEntries(PropertySettable target); + + @Nullable + IRawRule getRule(String name); + + IRawRule getBase(); + + IRawRule getSelf(); + + void setSelf(IRawRule raw); + + void setBase(IRawRule base); +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IRawRule.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IRawRule.java index 15b948a0d..db38f861d 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IRawRule.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/IRawRule.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,68 +11,60 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.types; - -import java.util.Collection; - -public interface IRawRule { - - Integer getId(); - - void setId(Integer id); - - String getInclude(); - - void setInclude(String include); - - String getName(); - - void setName(String name); - - String getContentName(); - - void setContentName(String name); - - String getMatch(); - - void setMatch(String match); - - IRawCaptures getCaptures(); - - void setCaptures(IRawCaptures captures); - - String getBegin(); - - void setBegin(String begin); - - IRawCaptures getBeginCaptures(); - - void setBeginCaptures(IRawCaptures beginCaptures); - - String getEnd(); - - void setEnd(String end); - - String getWhile(); - - IRawCaptures getEndCaptures(); - - void setEndCaptures(IRawCaptures endCaptures); - - IRawCaptures getWhileCaptures(); - - Collection getPatterns(); - - void setPatterns(Collection patterns); - - IRawRepository getRepository(); - - void setRepository(IRawRepository repository); - - boolean isApplyEndPatternLast(); - - void setApplyEndPatternLast(boolean applyEndPatternLast); -} + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.types; + +import java.util.Collection; + +import org.eclipse.jdt.annotation.Nullable; + +public interface IRawRule { + + @Nullable + Integer getId(); + + void setId(Integer id); + + @Nullable + String getInclude(); + + @Nullable + String getName(); + + @Nullable + String getContentName(); + + @Nullable + String getMatch(); + + @Nullable + IRawCaptures getCaptures(); + + @Nullable + String getBegin(); + + @Nullable + IRawCaptures getBeginCaptures(); + + @Nullable + String getEnd(); + + @Nullable + String getWhile(); + + @Nullable + IRawCaptures getEndCaptures(); + + @Nullable + IRawCaptures getWhileCaptures(); + + @Nullable + Collection getPatterns(); + + @Nullable + IRawRepository getRepository(); + + boolean isApplyEndPatternLast(); +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/package-info.java new file mode 100644 index 000000000..16526224a --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/types/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.core.internal.types; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/CloneUtils.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/CloneUtils.java deleted file mode 100644 index 0bbd390ca..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/CloneUtils.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.utils; - -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.stream.Collectors; - -import org.eclipse.tm4e.core.internal.grammar.parser.Raw; -import org.eclipse.tm4e.core.internal.types.IRawRepository; - -/** - * Clone utilities. - * - */ -public class CloneUtils { - - /** - * Helper class, use methods statically - */ - private CloneUtils() { - - } - - public static Object clone(Object value) { - if (value instanceof Raw) { - Raw rowToClone = (Raw) value; - Raw raw = new Raw(); - for (Entry entry : rowToClone.entrySet()) { - raw.put(entry.getKey(), clone(entry.getValue())); - } - return raw; - } else if (value instanceof List) { - return ((List) value).stream().map(CloneUtils::clone).collect(Collectors.toList()); - } else if (value instanceof String) { - return value; - } else if (value instanceof Integer) { - return value; - } else if (value instanceof Boolean) { - return value; - } - return value; - } - - public static IRawRepository mergeObjects(IRawRepository... sources) { - Raw target = new Raw(); - for (IRawRepository source : sources) { - Set> entries = ((Map) source).entrySet(); - for (Entry entry : entries) { - target.put(entry.getKey(), entry.getValue()); - } - } - return target; - } -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/CompareUtils.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/CompareUtils.java index 6eba78849..9227e3ca0 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/CompareUtils.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/CompareUtils.java @@ -1,57 +1,54 @@ -package org.eclipse.tm4e.core.internal.utils; - -import java.util.List; - -public class CompareUtils { - - public static int strcmp(String a, String b) { - if (a == null && b == null) { - return 0; - } - if (a == null) { - return -1; - } - if (b == null) { - return 1; - } -// if (a < b) { -// return -1; -// } -// if (a > b) { -// return 1; -// } -// return 0; - int result = a.compareTo(b); - if (result < 0 ) { - return -1; - } else if (result > 0 ) { - return 1; - } - return 0; - } - - public static int strArrCmp(List a, List b) { - if (a == null && b == null) { - return 0; - } - if (a == null) { - return -1; - } - if (b == null) { - return 1; - } - int len1 = a.size(); - int len2 = b.size(); - if (len1 == len2) { - for (int i = 0; i < len1; i++) { - int res = strcmp(a.get(i), b.get(i)); - if (res != 0) { - return res; - } - } - return 0; - } - return len1 - len2; - } - -} +package org.eclipse.tm4e.core.internal.utils; + +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; + +public final class CompareUtils { + + public static int strcmp(@Nullable final String a, @Nullable final String b) { + if (a == null && b == null) { + return 0; + } + if (a == null) { + return -1; + } + if (b == null) { + return 1; + } + final int result = a.compareTo(b); + if (result < 0) { + return -1; + } else if (result > 0) { + return 1; + } + return 0; + } + + public static int strArrCmp(@Nullable final List a, @Nullable final List b) { + if (a == null && b == null) { + return 0; + } + if (a == null) { + return -1; + } + if (b == null) { + return 1; + } + final int len1 = a.size(); + final int len2 = b.size(); + if (len1 == len2) { + for (int i = 0; i < len1; i++) { + final int res = strcmp(a.get(i), b.get(i)); + if (res != 0) { + return res; + } + } + return 0; + } + return len1 - len2; + } + + private CompareUtils() { + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/DeepCloneable.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/DeepCloneable.java new file mode 100644 index 000000000..ca63d74b5 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/DeepCloneable.java @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2022 Sebastian Thomschke and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.tm4e.core.internal.utils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + +import org.eclipse.jdt.annotation.Nullable; + +public interface DeepCloneable { + + @SuppressWarnings("unchecked") + public static T deepClone(final T obj) { + if (obj instanceof DeepCloneable) { + return (T) ((DeepCloneable) obj).deepClone(); + } + + if (obj instanceof List) { + final List<@Nullable Object> clone; + if (obj instanceof ArrayList) { + final var source = (ArrayList<@Nullable Object>) obj; + clone = (ArrayList<@Nullable Object>) source.clone(); + } else if (obj instanceof LinkedList) { + final var source = (LinkedList<@Nullable Object>) obj; + clone = (LinkedList<@Nullable Object>) source.clone(); + } else { + final var source = (List<@Nullable Object>) obj; + clone = new ArrayList<>(source); + } + clone.replaceAll(DeepCloneable::deepCloneNullable); + return (T) clone; + } + + if (obj instanceof Set) { + final Set<@Nullable Object> source; + final Set<@Nullable Object> clone; + if (obj instanceof TreeSet) { + final var cloneable = (TreeSet<@Nullable Object>) obj; + source = cloneable; + clone = (Set<@Nullable Object>) cloneable.clone(); + } else if (obj instanceof HashSet) { + final var cloneable = (HashSet<@Nullable Object>) obj; + source = cloneable; + clone = (Set<@Nullable Object>) cloneable.clone(); + } else { + source = (Set<@Nullable Object>) obj; + clone = new HashSet<>(); + } + clone.clear(); + for (final var e : source) { + clone.add(deepCloneNullable(e)); + } + return (T) clone; + } + + if (obj instanceof Map) { + if (obj instanceof HashMap) { + final var source = (HashMap) obj; + final var clone = (Map) source.clone(); + clone.replaceAll((k, v) -> deepCloneNullable(v)); + return (T) clone; + } + if (obj instanceof IdentityHashMap) { + final var source = (IdentityHashMap) obj; + final var clone = (Map) source.clone(); + clone.replaceAll((k, v) -> deepCloneNullable(v)); + return (T) clone; + } + if (obj instanceof TreeMap) { + final var source = (TreeMap) obj; + final var clone = (Map) source.clone(); + clone.replaceAll((k, v) -> deepCloneNullable(v)); + return (T) clone; + } + } + + // probably immutable + return obj; + } + + @Nullable + public static T deepCloneNullable(@Nullable final T obj) { + if (obj == null) { + return null; + } + return deepClone(obj); + } + + Object deepClone(); +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/MoreCollections.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/MoreCollections.java new file mode 100644 index 000000000..426cddcc6 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/MoreCollections.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2022 Sebastian Thomschke and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Sebastian Thomschke - initial implementation + */ +package org.eclipse.tm4e.core.internal.utils; + +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; + +public final class MoreCollections { + + @Nullable + public static T findLastElement(@Nullable final List list) { + if (list == null || list.isEmpty()) + return null; + return getLastElement(list); + } + + /** + * @param list a non-empty list with non-nullable elements + */ + public static T getLastElement(final List list) { + return list.get(list.size() - 1); + } + + /** + * Removes the last element in this list. + * + * @return the element previously at the specified position + * + * @throws UnsupportedOperationException if the {@code remove} operation is not supported by this list + * @throws IndexOutOfBoundsException if the list is empty + */ + public static T removeLastElement(final List list) { + return list.remove(list.size() - 1); + } + + private MoreCollections() { + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/NullSafetyHelper.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/NullSafetyHelper.java new file mode 100644 index 000000000..200a7dbda --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/NullSafetyHelper.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2022 Sebastian Thomschke and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Sebastian Thomschke - initial implementation + */ +package org.eclipse.tm4e.core.internal.utils; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +public final class NullSafetyHelper { + + /** + * Casts non-null value marked as {@link Nullable} to {@link NonNull}. + *

    + * Only use if you are sure the value is non-null but annotation-based null analysis was not able to determine it. + *

    + * This method is not meant for non-null input validation. + * + * @throws AssertionError if JVM assertions are enabled and the given value is null + */ + @NonNull + public static T castNonNull(@Nullable final T value) { + assert value != null; + return value; + } + + private NullSafetyHelper() { + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/RegexSource.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/RegexSource.java index 2906064e5..b85a2ef03 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/RegexSource.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/RegexSource.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,72 +11,128 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.internal.utils; - + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.internal.utils; + import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.eclipse.tm4e.core.internal.oniguruma.IOnigCaptureIndex; - -public class RegexSource { +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.oniguruma.OnigCaptureIndex; + +public final class RegexSource { /** * Helper class, access members statically */ private RegexSource() { } - - private static final Pattern CAPTURING_REGEX_SOURCE = Pattern - .compile("\\$(\\d+)|\\$\\{(\\d+):\\/(downcase|upcase)}"); - - public static boolean hasCaptures(String regexSource) { - if (regexSource == null) { - return false; - } - return CAPTURING_REGEX_SOURCE.matcher(regexSource).find(); - } - - public static String replaceCaptures(String regexSource, String captureSource, IOnigCaptureIndex[] captureIndices) { - Matcher m = CAPTURING_REGEX_SOURCE.matcher(regexSource); - StringBuffer result = new StringBuffer(); - while (m.find()) { - String match = m.group(); - String replacement = getReplacement(match, captureSource, captureIndices); - m.appendReplacement(result, replacement); - } - m.appendTail(result); - return result.toString(); - } - - private static String getReplacement(String match, String captureSource, IOnigCaptureIndex[] captureIndices) { - int index = -1; - String command = null; - int doublePointIndex = match.indexOf(':'); - if (doublePointIndex != -1) { - index = Integer.parseInt(match.substring(2, doublePointIndex)); - command = match.substring(doublePointIndex + 2, match.length() - 1); - } else { - index = Integer.parseInt(match.substring(1, match.length())); - } - IOnigCaptureIndex capture = captureIndices.length > index ? captureIndices[index] : null; - if (capture != null) { - String result = captureSource.substring(capture.getStart(), capture.getEnd()); - // Remove leading dots that would make the selector invalid - while (result.length() > 0 && result.charAt(0) == '.') { - result = result.substring(1); - } - if ("downcase".equals(command)) { - return result.toLowerCase(); - } else if ("upcase".equals(command)) { - return result.toUpperCase(); - } else { - return result; - } - } else { - return match; - } - } -} + + private static final Pattern CAPTURING_REGEX_SOURCE = Pattern + .compile("\\$(\\d+)|\\$\\{(\\d+):\\/(downcase|upcase)}"); + + /** + * Escapes/prefixes RegEx meta characters with a backslash in the given string. + * + * It is a non-regex based faster alternative to the TypeScript + * implementation: + * + *

    +	 * function escapeRegExpCharacters(value: string): string {
    +	 *   return value.replace(/[\-\\\{\}\*\+\?\|\^\$\.\,\[\]\(\)\#\s]/g, '\\$&');
    +	 * }
    +	 * 
    + * + * @return a string with the RegEx meta characters escaped + */ + public static String escapeRegExpCharacters(final String value) { + final int valueLen = value.length(); + final var sb = new StringBuilder(valueLen); + for (int i = 0; i < valueLen; i++) { + final char ch = value.charAt(i); + switch (ch) { + case '-': + case '\\': + case '{': + case '}': + case '*': + case '+': + case '?': + case '|': + case '^': + case '$': + case '.': + case ',': + case '[': + case ']': + case '(': + case ')': + case '#': + /* escaping white space chars is actually not necessary: + case ' ': + case '\t': + case '\n': + case '\f': + case '\r': + case 0x0B: // vertical tab \v + */ + sb.append('\\'); + } + sb.append(ch); + } + return sb.toString(); + } + + public static boolean hasCaptures(@Nullable final String regexSource) { + if (regexSource == null) { + return false; + } + return CAPTURING_REGEX_SOURCE.matcher(regexSource).find(); + } + + public static String replaceCaptures(final String regexSource, final String captureSource, + final OnigCaptureIndex[] captureIndices) { + final Matcher m = CAPTURING_REGEX_SOURCE.matcher(regexSource); + final StringBuilder result = new StringBuilder(); + while (m.find()) { + final String match = m.group(); + final String replacement = getReplacement(match, captureSource, captureIndices); + m.appendReplacement(result, replacement); + } + m.appendTail(result); + return result.toString(); + } + + private static String getReplacement(final String match, final String captureSource, + final OnigCaptureIndex[] captureIndices) { + final int index; + final String command; + final int doublePointIndex = match.indexOf(':'); + if (doublePointIndex != -1) { + index = Integer.parseInt(match.substring(2, doublePointIndex)); + command = match.substring(doublePointIndex + 2, match.length() - 1); + } else { + index = Integer.parseInt(match.substring(1)); + command = null; + } + final OnigCaptureIndex capture = captureIndices.length > index ? captureIndices[index] : null; + if (capture != null) { + String result = captureSource.substring(capture.start, capture.end); + // Remove leading dots that would make the selector invalid + while (!result.isEmpty() && result.charAt(0) == '.') { + result = result.substring(1); + } + if ("downcase".equals(command)) { + return result.toLowerCase(); + } + if ("upcase".equals(command)) { + return result.toUpperCase(); + } + return result; + } + return match; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/package-info.java new file mode 100644 index 000000000..110daeb6c --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/utils/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.core.internal.utils; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/AbstractLineList.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/AbstractLineList.java index 8b4827962..fcc9311a6 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/AbstractLineList.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/AbstractLineList.java @@ -1,90 +1,84 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * - * Contributors: - * Angelo Zerr - initial API and implementation + * Contributors: + * Angelo Zerr - initial API and implementation */ package org.eclipse.tm4e.core.model; +import static java.lang.System.Logger.Level.*; + +import java.lang.System.Logger; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.function.Consumer; -import java.util.logging.Level; -import java.util.logging.Logger; + +import org.eclipse.jdt.annotation.Nullable; /** - * Abstract class for Model lines used by the TextMate model. Implementation - * class must : + * Abstract class for Model lines used by the TextMate model. * + * Implementation class must: *
      *
    • synchronizes lines with the lines of the editor content when it changed.
    • *
    • call {@link AbstractLineList#invalidateLine(int)} with the first changed line.
    • *
    - * */ public abstract class AbstractLineList implements IModelLines { - private static final Logger LOGGER = Logger.getLogger(AbstractLineList.class.getName()); + private static final Logger LOGGER = System.getLogger(AbstractLineList.class.getName()); private final List list = Collections.synchronizedList(new ArrayList<>()); + @Nullable private TMModel model; - public AbstractLineList() { - } - - void setModel(TMModel model) { + protected void setModel(@Nullable final TMModel model) { this.model = model; } @Override - public void addLine(int line) { + public void addLine(final int line) { try { this.list.add(line, new ModelLine()); - } catch (Exception e) { + } catch (final Exception e) { e.printStackTrace(); } } @Override - public void removeLine(int line) { + public void removeLine(final int line) { this.list.remove(line); } @Override - public void updateLine(int line) { + public void updateLine(final int line) { try { - // this.list.get(line).text = this.lineToTextResolver.apply(line); - } catch (Exception e) { - LOGGER.log(Level.SEVERE, e.getMessage(), e); + // TODO this.list.get(line).text = this.lineToTextResolver.apply(line); + } catch (final Exception ex) { + LOGGER.log(ERROR, ex.getMessage(), ex); } } @Override - public ModelLine get(int index) { + public ModelLine get(final int index) { return this.list.get(index); } @Override - public void forEach(Consumer consumer) { + public void forEach(final Consumer consumer) { this.list.forEach(consumer); } - protected void invalidateLine(int lineIndex) { + protected void invalidateLine(final int lineIndex) { if (model != null) { model.invalidateLine(lineIndex); } } - - @Override - @Deprecated - public int getSize() { - return getNumberOfLines(); - } } \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/IModelLines.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/IModelLines.java index 2913610a9..6086be524 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/IModelLines.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/IModelLines.java @@ -1,74 +1,60 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.model; - -import java.util.function.Consumer; - -/** - * Mode lines API which must be initalize with a document and changed of - * document. - * - */ -public interface IModelLines { - - /** - * Add a new line at specified index line. - * - * @param lineIndex (0-based) - */ - void addLine(int lineIndex); - - /** - * Remove the line at specified index line. - * - * @param line (0-based) - */ - void removeLine(int lineIndex); - - /** - * Mark as line is updated. - * - * @param line (0-based) - */ - void updateLine(int lineIndex); - - /** - * @deprecated use {@link #getNumberOfLines()} - */ - @Deprecated - int getSize(); - - /** - * - * @param lineIndex (0-based) - * @return - */ - ModelLine get(int lineIndex); - - void forEach(Consumer consumer); - - int getNumberOfLines(); - - /** - * - * @param line (0-based) - * @return - * @throws Exception - */ - String getLineText(int lineIndex) throws Exception; - - int getLineLength(int lineIndex) throws Exception; - - void dispose(); - - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.model; + +import java.util.function.Consumer; + +/** + * Mode lines API which must be initalize with a document and changed of document. + */ +public interface IModelLines { + + /** + * Add a new line at specified index line. + * + * @param lineIndex (0-based) + */ + void addLine(int lineIndex); + + /** + * Remove the line at specified index line. + * + * @param line (0-based) + */ + void removeLine(int lineIndex); + + /** + * Mark as line is updated. + * + * @param line (0-based) + */ + void updateLine(int lineIndex); + + /** + * @param lineIndex (0-based) + * @throws IndexOutOfBoundsException + */ + ModelLine get(int lineIndex); + + void forEach(Consumer consumer); + + int getNumberOfLines(); + + /** + * @param line (0-based) + */ + String getLineText(int lineIndex) throws Exception; + + int getLineLength(int lineIndex) throws Exception; + + void dispose(); +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/IModelTokensChangedListener.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/IModelTokensChangedListener.java index 26b3d1533..5d265cec5 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/IModelTokensChangedListener.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/IModelTokensChangedListener.java @@ -1,19 +1,19 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.model; - -@FunctionalInterface -public interface IModelTokensChangedListener { - - void modelTokensChanged(ModelTokensChangedEvent e); - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.model; + +@FunctionalInterface +public interface IModelTokensChangedListener { + + void modelTokensChanged(ModelTokensChangedEvent event); + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ITMModel.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ITMModel.java index 5fbb089a1..1304464d5 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ITMModel.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ITMModel.java @@ -1,63 +1,62 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.model; - -import java.util.List; - -import org.eclipse.tm4e.core.grammar.IGrammar; - -/** - * TextMate model API. - * - */ -public interface ITMModel { - - /** - * Returns the TextMate grammar to use to parse for each lines of the - * document the TextMate tokens. - * - * @return the TextMate grammar to use to parse for each lines of the - * document the TextMate tokens. - */ - IGrammar getGrammar(); - - /** - * Set the TextMate grammar to use to parse for each lines of the document - * the TextMate tokens. - * - * @param grammar - */ - void setGrammar(IGrammar grammar); - - /** - * Add model tokens changed listener. - * - * @param listener - * to add - */ - void addModelTokensChangedListener(IModelTokensChangedListener listener); - - /** - * Remove model tokens changed listener. - * - * @param listener - * to remove - */ - void removeModelTokensChangedListener(IModelTokensChangedListener listener); - - void dispose(); - - List getLineTokens(int line); - - void forceTokenization(int lineNumber); - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.model; + +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.grammar.IGrammar; + +/** + * TextMate model API. + * + */ +public interface ITMModel { + + /** + * Returns the TextMate grammar to use to parse for each lines of the document the TextMate tokens. + * + * @return the TextMate grammar to use to parse for each lines of the document the TextMate tokens. + */ + @Nullable + IGrammar getGrammar(); + + /** + * Set the TextMate grammar to use to parse for each lines of the document the TextMate tokens. + */ + void setGrammar(IGrammar grammar); + + /** + * Add model tokens changed listener. + * + * @param listener to add + */ + void addModelTokensChangedListener(IModelTokensChangedListener listener); + + /** + * Remove model tokens changed listener. + * + * @param listener to remove + */ + void removeModelTokensChangedListener(IModelTokensChangedListener listener); + + void dispose(); + + /** + * @throws IndexOutOfBoundsException + */ + @Nullable + List getLineTokens(int line); + + void forceTokenization(int lineNumber); + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ITokenizationSupport.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ITokenizationSupport.java index 24bb86c27..6c68e1973 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ITokenizationSupport.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ITokenizationSupport.java @@ -13,18 +13,20 @@ * Contributors: * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.model; - -public interface ITokenizationSupport { - - TMState getInitialState(); - - LineTokens tokenize(String line, TMState state); - - // add offsetDelta to each of the returned indices - // stop tokenizing at absolute value stopAtOffset (i.e. stream.pos() + - // offsetDelta > stopAtOffset) - LineTokens tokenize(String line, TMState state, Integer offsetDelta, Integer stopAtOffset); - -} + */ +package org.eclipse.tm4e.core.model; + +import org.eclipse.jdt.annotation.Nullable; + +public interface ITokenizationSupport { + + TMState getInitialState(); + + LineTokens tokenize(String line, @Nullable TMState state); + + // add offsetDelta to each of the returned indices + // stop tokenizing at absolute value stopAtOffset (i.e. stream.pos() + + // offsetDelta > stopAtOffset) + LineTokens tokenize(String line, @Nullable TMState state, Integer offsetDelta, Integer stopAtOffset); + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/LineTokens.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/LineTokens.java index 99077f677..18c1fd073 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/LineTokens.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/LineTokens.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,34 +11,39 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.model; - -import java.util.List; - -public class LineTokens { - - List tokens; - int actualStopOffset; - TMState endState; - - public LineTokens(List tokens, int actualStopOffset, TMState endState) { - this.tokens = tokens; - this.actualStopOffset = actualStopOffset; - this.endState = endState; - } - - public TMState getEndState() { - return endState; - } - - public void setEndState(TMState endState) { - this.endState = endState; - } - - public List getTokens() { - return tokens; - } -} + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.model; + +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; + +public class LineTokens { + + final List tokens; + int actualStopOffset; + + @Nullable + TMState endState; + + public LineTokens(final List tokens, final int actualStopOffset, @Nullable final TMState endState) { + this.tokens = tokens; + this.actualStopOffset = actualStopOffset; + this.endState = endState; + } + + @Nullable + public TMState getEndState() { + return endState; + } + + public void setEndState(@Nullable final TMState endState) { + this.endState = endState; + } + + public List getTokens() { + return tokens; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ModelLine.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ModelLine.java index 9c042bec2..d8ac79f65 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ModelLine.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ModelLine.java @@ -1,47 +1,50 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.model; - -import java.util.List; - -public class ModelLine { - - //String text; - boolean isInvalid; - TMState state; - List tokens; - - public ModelLine(/*String text*/) { - //this.text = text; - } - - public void resetTokenizationState() { - this.state = null; - this.tokens = null; - } - - public TMState getState() { - return state; - } - - public void setState(TMState state) { - this.state = state; - } - - public void setTokens(List tokens) { - this.tokens = tokens; - } - - public List getTokens() { - return tokens; - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.model; + +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; + +public class ModelLine { + + boolean isInvalid; + + @Nullable + TMState state; + + @Nullable + List tokens; + + public void resetTokenizationState() { + this.state = null; + this.tokens = null; + } + + @Nullable + public TMState getState() { + return state; + } + + public void setState(@Nullable final TMState state) { + this.state = state; + } + + public void setTokens(@Nullable final List tokens) { + this.tokens = tokens; + } + + @Nullable + public List getTokens() { + return tokens; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ModelTokensChangedEvent.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ModelTokensChangedEvent.java index d2e2daa62..2b60c792c 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ModelTokensChangedEvent.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/ModelTokensChangedEvent.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,30 +11,28 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.model; - + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.model; + import java.util.Arrays; -import java.util.List; - -/** - * Model tokens changed event. - * - */ -public class ModelTokensChangedEvent { - - public final List ranges; - public final ITMModel model; - - public ModelTokensChangedEvent(Range range, ITMModel model) { - this(Arrays.asList(range), model); - } - - public ModelTokensChangedEvent(List ranges, ITMModel model) { - this.ranges = ranges; - this.model = model; - } - -} +import java.util.List; + +/** + * Model tokens changed event. + */ +public class ModelTokensChangedEvent { + + public final List ranges; + public final ITMModel model; + + public ModelTokensChangedEvent(final Range range, final ITMModel model) { + this(Arrays.asList(range), model); + } + + public ModelTokensChangedEvent(final List ranges, final ITMModel model) { + this.ranges = ranges; + this.model = model; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/Range.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/Range.java index f67ac1aec..d0961c465 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/Range.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/Range.java @@ -13,20 +13,19 @@ * Contributors: * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.model; - -public class Range { - - public final int fromLineNumber; - public int toLineNumber; + */ +package org.eclipse.tm4e.core.model; + +public class Range { + + public final int fromLineNumber; + public int toLineNumber; /** * Constructs a range made of a single line - * @param lineNumber - */ - public Range(int lineNumber) { - this.fromLineNumber = lineNumber; - this.toLineNumber = lineNumber; - } -} + */ + public Range(final int lineNumber) { + this.fromLineNumber = lineNumber; + this.toLineNumber = lineNumber; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/TMModel.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/TMModel.java index 4628a2c83..ebb9c9a39 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/TMModel.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/TMModel.java @@ -1,336 +1,347 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.model; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.PriorityBlockingQueue; -import java.util.function.Consumer; -import java.util.logging.Logger; - -import org.eclipse.tm4e.core.grammar.IGrammar; - -/** - * TextMate model class. - * - */ -public class TMModel implements ITMModel { - - private static final Logger LOGGER = Logger.getLogger(TMModel.class.getName()); - - /** - * The TextMate grammar to use to parse for each lines of the document the - * TextMate tokens. - **/ - private IGrammar grammar; - - /** Listener when TextMate model tokens changed **/ - private final List listeners; - - Tokenizer tokenizer; - - /** The background thread. */ - private TokenizerThread fThread; - - private final IModelLines lines; - private PriorityBlockingQueue invalidLines = new PriorityBlockingQueue<>(); - - public TMModel(IModelLines lines) { - this.listeners = new ArrayList<>(); - this.lines = lines; - ((AbstractLineList)lines).setModel(this); - lines.forEach(ModelLine::resetTokenizationState); - invalidateLine(0); - } - - /** - * The {@link TokenizerThread} takes as input an {@link TMModel} and continuously - * runs tokenizing in background on the lines found in {@link TMModel#lines}. - * The {@link TMModel#lines} are expected to be accessed through {@link TMModel#getLines()} - * and manipulated by the UI part to inform of needs to (re)tokenize area, then the {@link TokenizerThread} - * processes them and emits events through the model. UI elements are supposed to subscribe and react to the events with - * {@link TMModel#addModelTokensChangedListener(IModelTokensChangedListener)}. - * - */ - static class TokenizerThread extends Thread { - private TMModel model; - private TMState lastState; - - /** - * Creates a new background thread. The thread runs with minimal - * priority. - * - * @param name - * the thread's name - */ - public TokenizerThread(String name, TMModel model) { - super(name); - this.model = model; - setPriority(Thread.MIN_PRIORITY); - setDaemon(true); - } - - @Override - public void run() { - if (isInterrupted()) { - return; - } - - do { - try { - Integer toProcess = model.invalidLines.take(); - if (model.lines.get(toProcess).isInvalid) { - try { - this.revalidateTokensNow(toProcess.intValue(), null); - } catch (Exception t) { - LOGGER.severe(t.getMessage()); - if (toProcess < model.lines.getNumberOfLines()) { - model.invalidateLine(toProcess); - } - } - } - } catch (InterruptedException e) { - interrupt(); - } - } while (!isInterrupted() && model.fThread != null); - } - - /** - * - * @param startLine 0-based - * @param toLineIndexOrNull 0-based - */ - private void revalidateTokensNow(int startLine, Integer toLineIndexOrNull) { - model.buildEventWithCallback(eventBuilder -> { - Integer toLineIndex = toLineIndexOrNull; - if (toLineIndex == null || toLineIndex >= model.lines.getNumberOfLines()) { - toLineIndex = model.lines.getNumberOfLines() - 1; - } - - long tokenizedChars = 0; - long currentCharsToTokenize = 0; - final long MAX_ALLOWED_TIME = 20; - long currentEstimatedTimeToTokenize = 0; - long elapsedTime; - long startTime = System.currentTimeMillis(); - // Tokenize at most 1000 lines. Estimate the tokenization speed per - // character and stop when: - // - MAX_ALLOWED_TIME is reached - // - tokenizing the next line would go above MAX_ALLOWED_TIME - - int lineIndex = startLine; - while (lineIndex <= toLineIndex && lineIndex < model.getLines().getNumberOfLines()) { - elapsedTime = System.currentTimeMillis() - startTime; - if (elapsedTime > MAX_ALLOWED_TIME) { - // Stop if MAX_ALLOWED_TIME is reached - model.invalidateLine(lineIndex); - return; - } - - // Compute how many characters will be tokenized for this line - try { - currentCharsToTokenize = model.lines.getLineLength(lineIndex); - } catch (Exception e) { - LOGGER.severe(e.getMessage()); - } - - if (tokenizedChars > 0) { - // If we have enough history, estimate how long tokenizing this line would take - currentEstimatedTimeToTokenize = (long) ((double)elapsedTime / tokenizedChars) * currentCharsToTokenize; - if (elapsedTime + currentEstimatedTimeToTokenize > MAX_ALLOWED_TIME) { - // Tokenizing this line will go above MAX_ALLOWED_TIME - model.invalidateLine(lineIndex); - return; - } - } - - lineIndex = this.updateTokensInRange(eventBuilder, lineIndex, lineIndex) + 1; - tokenizedChars += currentCharsToTokenize; - } - }); - - } - - /** - * - * @param eventBuilder - * @param startIndex 0-based - * @param endLineIndex 0-based - * @param emitEvents - * @return the first line index (0-based) that was NOT processed by this operation - */ - private int updateTokensInRange(ModelTokensChangedEventBuilder eventBuilder, int startIndex, int endLineIndex) { - int stopLineTokenizationAfter = 1000000000; // 1 billion, if a line is - // so long, you have other - // trouble :). - // Validate all states up to and including endLineIndex - int nextInvalidLineIndex = startIndex; - int lineIndex = startIndex; - while (lineIndex <= endLineIndex && lineIndex < model.lines.getNumberOfLines()) { - int endStateIndex = lineIndex + 1; - LineTokens r = null; - String text = null; - ModelLine modeLine = model.lines.get(lineIndex); - try { - text = model.lines.getLineText(lineIndex); - // Tokenize only the first X characters - r = model.tokenizer.tokenize(text, modeLine.getState(), 0, stopLineTokenizationAfter); - } catch (Exception e) { - LOGGER.severe(e.getMessage()); - } - - if (r != null && r.tokens != null && !r.tokens.isEmpty()) { - // Cannot have a stop offset before the last token - r.actualStopOffset = Math.max(r.actualStopOffset, r.tokens.get(r.tokens.size() - 1).startIndex + 1); - } - - if (r != null && r.actualStopOffset < text.length()) { - // Treat the rest of the line (if above limit) as one default token - r.tokens.add(new TMToken(r.actualStopOffset, "")); - // Use as end state the starting state - r.endState = modeLine.getState(); - } - - if (r == null) { - r = new LineTokens(Collections.singletonList(new TMToken(0, "")), text.length(), modeLine.getState()); - } - modeLine.setTokens(r.tokens); - eventBuilder.registerChangedTokens(lineIndex + 1); - modeLine.isInvalid = false; - - if (endStateIndex < model.lines.getNumberOfLines()) { - ModelLine endStateLine = model.lines.get(endStateIndex); - if (endStateLine.getState() != null && r.endState.equals(endStateLine.getState())) { - // The end state of this line remains the same - nextInvalidLineIndex = lineIndex + 1; - while (nextInvalidLineIndex < model.lines.getNumberOfLines()) { - boolean isLastLine = nextInvalidLineIndex + 1 >= model.lines.getNumberOfLines(); - if (model.lines.get(nextInvalidLineIndex).isInvalid - || (!isLastLine && model.lines.get(nextInvalidLineIndex + 1).getState() == null) - || (isLastLine && this.lastState == null)) { - break; - } - nextInvalidLineIndex++; - } - lineIndex = nextInvalidLineIndex; - } else { - endStateLine.setState(r.endState); - lineIndex++; - } - } else { - this.lastState = r.endState; - lineIndex++; - } - } - return nextInvalidLineIndex; - } - - } - - @Override - public IGrammar getGrammar() { - return grammar; - } - - @Override - public void setGrammar(IGrammar grammar) { - if (!Objects.equals(grammar, this.grammar)) { - this.grammar = grammar; - this.tokenizer = new Tokenizer(grammar); - lines.get(0).setState(tokenizer.getInitialState()); - } - } - - @Override - public void addModelTokensChangedListener(IModelTokensChangedListener listener) { - if (this.fThread == null || this.fThread.isInterrupted()) { - this.fThread = new TokenizerThread(getClass().getName(), this); - } - if (!this.fThread.isAlive()) { - this.fThread.start(); - } - if (!listeners.contains(listener)) { - listeners.add(listener); - } - } - - @Override - public void removeModelTokensChangedListener(IModelTokensChangedListener listener) { - listeners.remove(listener); - if (listeners.isEmpty()) { - // no need to keep tokenizing if no-one cares - stop(); - } - } - - @Override - public void dispose() { - stop(); - getLines().dispose(); - } - - /** - * Interrupt the thread. - */ - private void stop() { - if (fThread == null) { - return; - } - this.fThread.interrupt(); - this.fThread = null; - } - - private void buildEventWithCallback(Consumer callback) { - ModelTokensChangedEventBuilder eventBuilder = new ModelTokensChangedEventBuilder(this); - - callback.accept(eventBuilder); - - ModelTokensChangedEvent e = eventBuilder.build(); - if (e != null) { - this.emit(e); - } - } - - private void emit(ModelTokensChangedEvent e) { - for (IModelTokensChangedListener listener : listeners) { - listener.modelTokensChanged(e); - } - } - - @Override - public void forceTokenization(int lineNumber) { - this.buildEventWithCallback(eventBuilder -> - this.fThread.updateTokensInRange(eventBuilder, lineNumber, lineNumber) - ); - } - - @Override - public List getLineTokens(int lineNumber) { - return lines.get(lineNumber).tokens; - } - - public boolean isLineInvalid(int lineNumber) { - return lines.get(lineNumber).isInvalid; - } - - void invalidateLine(int lineIndex) { - this.lines.get(lineIndex).isInvalid = true; - this.invalidLines.add(lineIndex); - } - - public IModelLines getLines() { - return this.lines; - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.model; + +import static java.lang.System.Logger.Level.*; +import static org.eclipse.tm4e.core.internal.utils.MoreCollections.*; +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import java.lang.System.Logger; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.PriorityBlockingQueue; +import java.util.function.Consumer; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.grammar.IGrammar; +import org.eclipse.tm4e.core.internal.model.ModelTokensChangedEventBuilder; + +/** + * TextMate model class. + */ +public class TMModel implements ITMModel { + + private static final Logger LOGGER = System.getLogger(TMModel.class.getName()); + + /** The TextMate grammar to use to parse for each lines of the document the TextMate tokens. **/ + @Nullable + private IGrammar grammar; + + /** Listener when TextMate model tokens changed **/ + private final Set listeners = new CopyOnWriteArraySet<>(); + + @Nullable + private Tokenizer tokenizer; + + /** The background thread. */ + @Nullable + private volatile TokenizerThread fThread; + + private final IModelLines lines; + private final PriorityBlockingQueue invalidLines = new PriorityBlockingQueue<>(); + + public TMModel(final IModelLines lines) { + this.lines = lines; + if (lines instanceof AbstractLineList) { + ((AbstractLineList) lines).setModel(this); + } + lines.forEach(ModelLine::resetTokenizationState); + invalidateLine(0); + } + + /** + * The {@link TokenizerThread} takes as input an {@link TMModel} and continuously runs tokenizing in background on + * the lines found in {@link TMModel#lines}. + * + * The {@link TMModel#lines} are expected to be accessed through {@link TMModel#getLines()} and manipulated by the + * UI part to inform of needs to (re)tokenize area, then the {@link TokenizerThread} processes them and emits events + * through the model. + * + * UI elements are supposed to subscribe and react to the events with + * {@link TMModel#addModelTokensChangedListener(IModelTokensChangedListener)}. + */ + private static final class TokenizerThread extends Thread { + private final TMModel model; + + @Nullable + private TMState lastState; + + /** + * Creates a new background thread. The thread runs with minimal priority. + * + * @param name the thread's name + */ + TokenizerThread(final String name, final TMModel model) { + super(name); + this.model = model; + setPriority(Thread.MIN_PRIORITY); + setDaemon(true); + } + + @Override + public void run() { + while (!isInterrupted() && model.fThread == this) { + try { + final int toProcess = model.invalidLines.take().intValue(); + if (model.lines.get(toProcess).isInvalid) { + try { + revalidateTokensNow(toProcess, null); + } catch (final Exception ex) { + LOGGER.log(ERROR, ex.getMessage()); + if (toProcess < model.lines.getNumberOfLines()) { + model.invalidateLine(toProcess); + } + } + } + } catch (final InterruptedException e) { + interrupt(); + } + } + } + + /** + * @param startLine 0-based + * @param toLineIndexOrNull 0-based + */ + private void revalidateTokensNow(final int startLine, @Nullable final Integer toLineIndexOrNull) { + model.buildAndEmitEvent(eventBuilder -> { + final int toLineIndex; + if (toLineIndexOrNull == null || toLineIndexOrNull >= model.lines.getNumberOfLines()) { + toLineIndex = model.lines.getNumberOfLines() - 1; + } else { + toLineIndex = toLineIndexOrNull; + } + + long tokenizedChars = 0; + long currentCharsToTokenize = 0; + final long MAX_ALLOWED_TIME = 20; + long currentEstimatedTimeToTokenize = 0; + long elapsedTime; + final long startTime = System.currentTimeMillis(); + // Tokenize at most 1000 lines. Estimate the tokenization speed per character and stop when: + // - MAX_ALLOWED_TIME is reached + // - tokenizing the next line would go above MAX_ALLOWED_TIME + + int lineIndex = startLine; + while (lineIndex <= toLineIndex && lineIndex < model.lines.getNumberOfLines()) { + elapsedTime = System.currentTimeMillis() - startTime; + if (elapsedTime > MAX_ALLOWED_TIME) { + // Stop if MAX_ALLOWED_TIME is reached + model.invalidateLine(lineIndex); + return; + } + + // Compute how many characters will be tokenized for this line + try { + currentCharsToTokenize = model.lines.getLineLength(lineIndex); + } catch (final Exception ex) { + LOGGER.log(ERROR, ex.getMessage()); + } + + if (tokenizedChars > 0) { + // If we have enough history, estimate how long tokenizing this line would take + currentEstimatedTimeToTokenize = (long) ((double) elapsedTime / tokenizedChars) + * currentCharsToTokenize; + if (elapsedTime + currentEstimatedTimeToTokenize > MAX_ALLOWED_TIME) { + // Tokenizing this line will go above MAX_ALLOWED_TIME + model.invalidateLine(lineIndex); + return; + } + } + + lineIndex = updateTokensInRange(eventBuilder, lineIndex, lineIndex) + 1; + tokenizedChars += currentCharsToTokenize; + } + }); + + } + + /** + * @param startIndex 0-based + * @param endLineIndex 0-based + * + * @return the first line index (0-based) that was NOT processed by this operation + */ + private int updateTokensInRange(final ModelTokensChangedEventBuilder eventBuilder, final int startIndex, + final int endLineIndex) { + final int stopLineTokenizationAfter = 1_000_000_000; // 1 billion, if a line is so long, you have other + // trouble :) + + // Validate all states up to and including endLineIndex + int nextInvalidLineIndex = startIndex; + int lineIndex = startIndex; + while (lineIndex <= endLineIndex && lineIndex < model.lines.getNumberOfLines()) { + final int endStateIndex = lineIndex + 1; + LineTokens r = null; + String text = null; + final ModelLine modeLine = model.lines.get(lineIndex); + try { + text = model.lines.getLineText(lineIndex); + // Tokenize only the first X characters + r = castNonNull(model.tokenizer).tokenize(text, modeLine.state, 0, stopLineTokenizationAfter); + } catch (final Exception ex) { + LOGGER.log(ERROR, ex.toString()); + return nextInvalidLineIndex; + } + + if (!r.tokens.isEmpty()) { + // Cannot have a stop offset before the last token + r.actualStopOffset = Math.max(r.actualStopOffset, getLastElement(r.tokens).startIndex + 1); + } + + if (r.actualStopOffset < text.length()) { + // Treat the rest of the line (if above limit) as one default token + r.tokens.add(new TMToken(r.actualStopOffset, "")); + // Use as end state the starting state + r.endState = modeLine.getState(); + } + + modeLine.setTokens(r.tokens); + eventBuilder.registerChangedTokens(lineIndex + 1); + modeLine.isInvalid = false; + + if (endStateIndex < model.lines.getNumberOfLines()) { + final ModelLine endStateLine = castNonNull(model.lines.get(endStateIndex)); + if (endStateLine.getState() != null && Objects.equals(endStateLine.getState(), r.endState)) { + // The end state of this line remains the same + nextInvalidLineIndex = lineIndex + 1; + while (nextInvalidLineIndex < model.lines.getNumberOfLines()) { + if (model.lines.get(nextInvalidLineIndex).isInvalid) { + break; + } + final var isLastLine = nextInvalidLineIndex + 1 >= model.lines.getNumberOfLines(); + if (isLastLine + ? lastState == null + : model.lines.get(nextInvalidLineIndex + 1).getState() == null) { + break; + } + nextInvalidLineIndex++; + } + lineIndex = nextInvalidLineIndex; + } else { + endStateLine.setState(r.endState); + lineIndex++; + } + } else { + lastState = r.endState; + lineIndex++; + } + } + return nextInvalidLineIndex; + } + } + + @Nullable + @Override + public IGrammar getGrammar() { + return grammar; + } + + @Override + public void setGrammar(final IGrammar grammar) { + if (!Objects.equals(grammar, this.grammar)) { + this.grammar = grammar; + final var tokenizer = this.tokenizer = new Tokenizer(grammar); + lines.get(0).setState(tokenizer.getInitialState()); + } + } + + @Override + public synchronized void addModelTokensChangedListener(final IModelTokensChangedListener listener) { + listeners.add(listener); + + var fThread = this.fThread; + if (fThread == null || fThread.isInterrupted()) { + fThread = this.fThread = new TokenizerThread(getClass().getName(), this); + } + if (!fThread.isAlive()) { + fThread.start(); + } + } + + @Override + public synchronized void removeModelTokensChangedListener(final IModelTokensChangedListener listener) { + listeners.remove(listener); + + if (listeners.isEmpty()) { + // no need to keep tokenizing if no-one cares + stop(); + } + } + + @Override + public void dispose() { + stop(); + lines.dispose(); + } + + /** + * Interrupt the thread. + */ + private synchronized void stop() { + final var fThread = this.fThread; + if (fThread == null) { + return; + } + fThread.interrupt(); + this.fThread = null; + } + + private void buildAndEmitEvent(final Consumer callback) { + final ModelTokensChangedEventBuilder eventBuilder = new ModelTokensChangedEventBuilder(this); + + callback.accept(eventBuilder); + + final ModelTokensChangedEvent event = eventBuilder.build(); + if (event != null) { + emit(event); + } + } + + private void emit(final ModelTokensChangedEvent e) { + for (final IModelTokensChangedListener listener : listeners) { + listener.modelTokensChanged(e); + } + } + + @Override + public void forceTokenization(final int lineNumber) { + final var tokenizerThread = this.fThread; + if (tokenizerThread == null) { + return; + } + buildAndEmitEvent(eventBuilder -> tokenizerThread.updateTokensInRange(eventBuilder, lineNumber, lineNumber)); + } + + @Override + @Nullable + public List getLineTokens(final int lineNumber) { + return lines.get(lineNumber).tokens; + } + + /** + * @throws IndexOutOfBoundsException + */ + public boolean isLineInvalid(final int lineNumber) { + return lines.get(lineNumber).isInvalid; + } + + /** + * @throws IndexOutOfBoundsException + */ + void invalidateLine(final int lineIndex) { + lines.get(lineIndex).isInvalid = true; + invalidLines.add(lineIndex); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/TMState.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/TMState.java index a473b8ae1..e9d989b87 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/TMState.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/TMState.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,52 +11,58 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.model; - + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.model; + import java.util.Objects; -import org.eclipse.tm4e.core.grammar.StackElement; - -public class TMState { - - private TMState parentEmbedderState; - private StackElement ruleStack; - - public TMState(TMState parentEmbedderState, StackElement ruleStatck) { - this.parentEmbedderState = parentEmbedderState; - this.ruleStack = ruleStatck; - } - - public void setRuleStack(StackElement ruleStack) { - this.ruleStack = ruleStack; - } - - public StackElement getRuleStack() { - return ruleStack; - } - - @Override - public TMState clone() { - TMState parentEmbedderStateClone = this.parentEmbedderState != null ? this.parentEmbedderState.clone() : null; - return new TMState(parentEmbedderStateClone, this.ruleStack); - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof TMState)) { - return false; - } - TMState otherState = (TMState) other; - return Objects.equals(this.parentEmbedderState, otherState.parentEmbedderState) && - Objects.equals(this.ruleStack, otherState.ruleStack); +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.grammar.IStackElement; + +public class TMState { + + @Nullable + private final TMState parentEmbedderState; + + @Nullable + private IStackElement ruleStack; + + public TMState(@Nullable final TMState parentEmbedderState, @Nullable final IStackElement ruleStatck) { + this.parentEmbedderState = parentEmbedderState; + this.ruleStack = ruleStatck; + } + + public void setRuleStack(final IStackElement ruleStack) { + this.ruleStack = ruleStack; + } + + @Nullable + public IStackElement getRuleStack() { + return ruleStack; + } + + @Override + public TMState clone() { + final TMState parentEmbedderStateClone = this.parentEmbedderState != null + ? this.parentEmbedderState.clone() + : null; + return new TMState(parentEmbedderStateClone, this.ruleStack); + } + + @Override + public boolean equals(@Nullable final Object other) { + if (!(other instanceof TMState)) { + return false; + } + final TMState otherState = (TMState) other; + return Objects.equals(this.parentEmbedderState, otherState.parentEmbedderState) + && Objects.equals(this.ruleStack, otherState.ruleStack); } @Override public int hashCode() { return Objects.hash(this.parentEmbedderState, this.ruleStack); - } - -} + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/TMToken.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/TMToken.java index b08d212f2..38e554063 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/TMToken.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/TMToken.java @@ -13,16 +13,16 @@ * Contributors: * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.model; - -public class TMToken { - - public final int startIndex; - public final String type; - - public TMToken(int startIndex, String type) { - this.startIndex = startIndex; - this.type = type; - } -} + */ +package org.eclipse.tm4e.core.model; + +public class TMToken { + + public final int startIndex; + public final String type; + + public TMToken(final int startIndex, final String type) { + this.startIndex = startIndex; + this.type = type; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/Tokenizer.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/Tokenizer.java index 89e4eb802..debc99fb5 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/Tokenizer.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/Tokenizer.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,108 +11,107 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.model; - + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.model; + import java.util.ArrayList; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tm4e.core.grammar.IGrammar; -import org.eclipse.tm4e.core.grammar.IToken; -import org.eclipse.tm4e.core.grammar.ITokenizeLineResult; - -public class Tokenizer implements ITokenizationSupport { - - private final IGrammar grammar; - private final DecodeMap decodeMap; - - public Tokenizer(IGrammar grammar) { - this.grammar = grammar; - this.decodeMap = new DecodeMap(); - } - - @Override - public TMState getInitialState() { - return new TMState(null, null); - } - - @Override - public LineTokens tokenize(String line, TMState state) { - return tokenize(line, state, null, null); - } - - @Override - public LineTokens tokenize(String line, TMState state, Integer offsetDelta, Integer stopAtOffset) { - if (offsetDelta == null) { - offsetDelta = 0; - } - // Do not attempt to tokenize if a line has over 20k - // or if the rule stack contains more than 100 rules (indicator of - // broken grammar that forgets to pop rules) - // if (line.length >= 20000 || depth(state.ruleStack) > 100) { - // return new RawLineTokens( - // [new Token(offsetDelta, '')], - // [new ModeTransition(offsetDelta, this._modeId)], - // offsetDelta, - // state - // ); - // } - TMState freshState = state != null ? state.clone() : getInitialState(); - ITokenizeLineResult textMateResult = grammar.tokenizeLine(line, freshState.getRuleStack()); - freshState.setRuleStack(textMateResult.getRuleStack()); - - // Create the result early and fill in the tokens later - List tokens = new ArrayList<>(); - String lastTokenType = null; - for (int tokenIndex = 0, len = textMateResult.getTokens().length; tokenIndex < len; tokenIndex++) { - IToken token = textMateResult.getTokens()[tokenIndex]; - int tokenStartIndex = token.getStartIndex(); - String tokenType = decodeTextMateToken(this.decodeMap, token.getScopes().toArray(new String[0])); - - // do not push a new token if the type is exactly the same (also - // helps with ligatures) - if (!tokenType.equals(lastTokenType)) { - tokens.add(new TMToken(tokenStartIndex + offsetDelta, tokenType)); - lastTokenType = tokenType; - } - } - return new LineTokens(tokens, offsetDelta + line.length(), freshState); - - } - - private String decodeTextMateToken(DecodeMap decodeMap, String[] scopes) { - String[] prevTokenScopes = decodeMap.prevToken.scopes; - int prevTokenScopesLength = prevTokenScopes.length; - Map> prevTokenScopeTokensMaps = decodeMap.prevToken.scopeTokensMaps; - - Map> scopeTokensMaps = new LinkedHashMap<>(); - Map prevScopeTokensMaps = new LinkedHashMap<>(); - boolean sameAsPrev = true; - for (int level = 1/* deliberately skip scope 0 */; level < scopes.length; level++) { - String scope = scopes[level]; - - if (sameAsPrev) { - if (level < prevTokenScopesLength && prevTokenScopes[level].equals(scope)) { - prevScopeTokensMaps = prevTokenScopeTokensMaps.get(level); - scopeTokensMaps.put(level, prevScopeTokensMaps); - continue; - } - sameAsPrev = false; - } - - int[] tokens = decodeMap.getTokenIds(scope); - prevScopeTokensMaps = new LinkedHashMap<>(prevScopeTokensMaps); - for (int token : tokens) { - prevScopeTokensMaps.put(token, true); - } - scopeTokensMaps.put(level, prevScopeTokensMaps); - } - - decodeMap.prevToken = new TMTokenDecodeData(scopes, scopeTokensMaps); - return decodeMap.getToken(prevScopeTokensMaps); - } -} +import org.eclipse.tm4e.core.internal.model.DecodeMap; +import org.eclipse.tm4e.core.internal.model.TMTokenDecodeData; + +public class Tokenizer implements ITokenizationSupport { + + private final IGrammar grammar; + private final DecodeMap decodeMap = new DecodeMap(); + + public Tokenizer(final IGrammar grammar) { + this.grammar = grammar; + } + + @Override + public TMState getInitialState() { + return new TMState(null, null); + } + + @Override + public LineTokens tokenize(final String line, @Nullable final TMState state) { + return tokenize(line, state, null, null); + } + + @Override + public LineTokens tokenize(final String line, @Nullable final TMState state, @Nullable final Integer offsetDeltaOrNull, + @Nullable final Integer stopAtOffset) { + /* + Do not attempt to tokenize if a line has over 20k or + if the rule stack contains more than 100 rules (indicator of broken grammar that forgets to pop rules) + + if (line.length >= 20000 || depth(state.ruleStack) > 100) { + return new RawLineTokens( + [new Token(offsetDelta, '')], + [new ModeTransition(offsetDelta, this._modeId)], + offsetDelta, + state + ); + } + */ + final int offsetDelta = offsetDeltaOrNull == null ? 0 : offsetDeltaOrNull; + final var freshState = state != null ? state.clone() : getInitialState(); + final var textMateResult = grammar.tokenizeLine(line, freshState.getRuleStack()); + freshState.setRuleStack(textMateResult.getRuleStack()); + + // Create the result early and fill in the tokens later + final var tokens = new ArrayList(); + String lastTokenType = null; + for (int tokenIndex = 0, len = textMateResult.getTokens().length; tokenIndex < len; tokenIndex++) { + final var token = textMateResult.getTokens()[tokenIndex]; + final int tokenStartIndex = token.getStartIndex(); + final var tokenType = decodeTextMateToken(this.decodeMap, token.getScopes().toArray(String[]::new)); + + // do not push a new token if the type is exactly the same (also helps with ligatures) + if (!tokenType.equals(lastTokenType)) { + tokens.add(new TMToken(tokenStartIndex + offsetDelta, tokenType)); + lastTokenType = tokenType; + } + } + return new LineTokens(tokens, offsetDelta + line.length(), freshState); + + } + + private String decodeTextMateToken(final DecodeMap decodeMap, final String[] scopes) { + final String[] prevTokenScopes = decodeMap.prevToken.scopes; + final int prevTokenScopesLength = prevTokenScopes.length; + final var prevTokenScopeTokensMaps = decodeMap.prevToken.scopeTokensMaps; + + final var scopeTokensMaps = new LinkedHashMap>(); + Map prevScopeTokensMaps = new LinkedHashMap<>(); + boolean sameAsPrev = true; + for (int level = 1/* deliberately skip scope 0 */; level < scopes.length; level++) { + final String scope = scopes[level]; + + if (sameAsPrev) { + if (level < prevTokenScopesLength && prevTokenScopes[level].equals(scope)) { + prevScopeTokensMaps = prevTokenScopeTokensMaps.get(level); + scopeTokensMaps.put(level, prevScopeTokensMaps); + continue; + } + sameAsPrev = false; + } + + final int[] tokens = decodeMap.getTokenIds(scope); + prevScopeTokensMaps = new LinkedHashMap<>(prevScopeTokensMaps); + for (final int token : tokens) { + prevScopeTokensMaps.put(token, true); + } + scopeTokensMaps.put(level, prevScopeTokensMaps); + } + + decodeMap.prevToken = new TMTokenDecodeData(scopes, scopeTokensMaps); + return decodeMap.getToken(prevScopeTokensMaps); + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/package-info.java new file mode 100644 index 000000000..c72badf4a --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/model/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.core.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/registry/IRegistryOptions.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/registry/IRegistryOptions.java index 0ea3e58bb..465ce707c 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/registry/IRegistryOptions.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/registry/IRegistryOptions.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,46 +11,65 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.core.registry; - + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.core.registry; + import java.io.IOException; import java.io.InputStream; import java.util.Collection; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.theme.IRawTheme; + +/** + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/main.ts + */ +public interface IRegistryOptions { + + IRegistryOptions DEFAULT_LOCATOR = new IRegistryOptions() { + + @Nullable + @Override + public String getFilePath(final String scopeName) { + return null; + } + + @Nullable + @Override + public InputStream getInputStream(final String scopeName) { + return null; + } -import org.eclipse.tm4e.core.theme.IRawTheme; - -public interface IRegistryOptions { - - public static final IRegistryOptions DEFAULT_LOCATOR = new IRegistryOptions() { - - @Override - public String getFilePath(String scopeName) { - return null; - } - - @Override - public InputStream getInputStream(String scopeName) { - return null; - } - - @Override - public Collection getInjections(String scopeName) { - return null; + @Nullable + @Override + public Collection getInjections(final String scopeName) { + return null; } - - }; - + + }; + + @Nullable default IRawTheme getTheme() { return null; } - - String getFilePath(String scopeName); - - InputStream getInputStream(String scopeName) throws IOException; - - Collection getInjections(String scopeName); - -} + + @Nullable + default List getColorMap() { + return null; + } + + @Nullable + String getFilePath(String scopeName); + + @Nullable + InputStream getInputStream(String scopeName) throws IOException; + + @Nullable + Collection<@NonNull String> getInjections(String scopeName); +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/registry/Registry.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/registry/Registry.java index 19a6e2e50..b020681c8 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/registry/Registry.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/registry/Registry.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,8 +11,8 @@ * Initial license: MIT * * Contributors: - * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java + * - Microsoft Corporation: Initial code, written in TypeScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java */ package org.eclipse.tm4e.core.registry; @@ -20,45 +20,48 @@ import java.io.FileInputStream; import java.io.InputStream; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tm4e.core.TMException; import org.eclipse.tm4e.core.grammar.IGrammar; import org.eclipse.tm4e.core.internal.grammar.reader.GrammarReader; -import org.eclipse.tm4e.core.internal.grammars.SyncRegistry; -import org.eclipse.tm4e.core.internal.types.IRawGrammar; -import org.eclipse.tm4e.core.theme.IRawTheme; -import org.eclipse.tm4e.core.theme.Theme; +import org.eclipse.tm4e.core.internal.registry.SyncRegistry; +import org.eclipse.tm4e.core.internal.theme.IRawTheme; +import org.eclipse.tm4e.core.internal.theme.Theme; /** * The registry that will hold all grammars. * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/main.ts + * TODO outdated compared to upstream as of: + * https://github.com/microsoft/vscode-textmate/commit/b166b75fa72d2dd3efce0d68c98c2bd10adc1ef1 + * + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/main.ts * */ public class Registry { - private final IRegistryOptions locator; + private final IRegistryOptions options; private final SyncRegistry syncRegistry; public Registry() { this(IRegistryOptions.DEFAULT_LOCATOR); } - public Registry(IRegistryOptions locator) { - this.locator = locator; - this.syncRegistry = new SyncRegistry(Theme.createFromRawTheme(locator.getTheme())); + public Registry(final IRegistryOptions options) { + this.options = options; + this.syncRegistry = new SyncRegistry(Theme.createFromRawTheme(options.getTheme(), options.getColorMap())); } /** - * Change the theme. Once called, no previous `ruleStack` should be used - * anymore. + * Change the theme. Once called, no previous `ruleStack` should be used anymore. */ - public void setTheme(IRawTheme theme) { - this.syncRegistry.setTheme(Theme.createFromRawTheme(theme)); + public void setTheme(final IRawTheme theme) { + this.syncRegistry.setTheme(Theme.createFromRawTheme(theme, options.getColorMap())); } /** @@ -68,53 +71,45 @@ public Set getColorMap() { return this.syncRegistry.getColorMap(); } - public IGrammar loadGrammar(String initialScopeName) { - return _loadGrammar(initialScopeName); - } - - private IGrammar _loadGrammar(String initialScopeName) { - - List remainingScopeNames = new ArrayList<>(); + @Nullable + public IGrammar loadGrammar(final String initialScopeName) { + final List remainingScopeNames = new ArrayList<>(); remainingScopeNames.add(initialScopeName); - List seenScopeNames = new ArrayList<>(); + final List seenScopeNames = new ArrayList<>(); seenScopeNames.add(initialScopeName); while (!remainingScopeNames.isEmpty()) { - String scopeName = remainingScopeNames.remove(0); // shift(); + final String scopeName = remainingScopeNames.remove(0); if (this.syncRegistry.lookup(scopeName) != null) { continue; } - String filePath = this.locator.getFilePath(scopeName); + final String filePath = this.options.getFilePath(scopeName); if (filePath == null) { if (scopeName.equals(initialScopeName)) { throw new TMException("Unknown location for grammar <" + initialScopeName + ">"); - // callback(new Error('Unknown location for grammar <' + - // initialScopeName + '>'), null); - // return; } continue; } - try { - InputStream in = this.locator.getInputStream(scopeName); - IRawGrammar grammar = GrammarReader.readGrammarSync(filePath, in); - Collection injections = this.locator.getInjections(scopeName); + try (InputStream in = this.options.getInputStream(scopeName)) { + if (in == null) { + throw new TMException("Unknown location for grammar <" + initialScopeName + ">"); + } + final var grammar = GrammarReader.readGrammarSync(filePath, in); + final var injections = this.options.getInjections(scopeName); - Collection deps = this.syncRegistry.addGrammar(grammar, injections); - for (String dep : deps) { + final var deps = this.syncRegistry.addGrammar(grammar, injections); + for (final String dep : deps) { if (!seenScopeNames.contains(dep)) { seenScopeNames.add(dep); remainingScopeNames.add(dep); } } - } catch (Throwable e) { + } catch (final Exception e) { if (scopeName.equals(initialScopeName)) { - // callback(new Error('Unknown location for grammar <' + - // initialScopeName + '>'), null); - // return; throw new TMException("Unknown location for grammar <" + initialScopeName + ">", e); } } @@ -122,40 +117,47 @@ private IGrammar _loadGrammar(String initialScopeName) { return this.grammarForScopeName(initialScopeName); } - public IGrammar loadGrammarFromPathSync(File file) throws Exception { - return loadGrammarFromPathSync(file.getPath(), new FileInputStream(file)); + @Nullable + public IGrammar loadGrammarFromPathSync(final File file) throws Exception { + try (InputStream is = new FileInputStream(file)) { + return loadGrammarFromPathSync(file.getPath(), is); + } } - public IGrammar loadGrammarFromPathSync(String path, InputStream in) throws Exception { + @Nullable + public IGrammar loadGrammarFromPathSync(final String path, final InputStream in) throws Exception { return loadGrammarFromPathSync(path, in, 0, null); } /** * Load the grammar at `path` synchronously. - * - * @throws Exception */ - public IGrammar loadGrammarFromPathSync(String path, InputStream in, int initialLanguage, - Map embeddedLanguages) throws Exception { - IRawGrammar rawGrammar = GrammarReader.readGrammarSync(path, in); - Collection injections = this.locator.getInjections(rawGrammar.getScopeName()); + @Nullable + public IGrammar loadGrammarFromPathSync(final String path, final InputStream in, final int initialLanguage, + @Nullable final Map embeddedLanguages) throws Exception { + final var rawGrammar = GrammarReader.readGrammarSync(path, in); + final var injections = this.options.getInjections(rawGrammar.getScopeName()); this.syncRegistry.addGrammar(rawGrammar, injections); return this.grammarForScopeName(rawGrammar.getScopeName(), initialLanguage, embeddedLanguages); } - public IGrammar grammarForScopeName(String scopeName) { + @Nullable + public IGrammar grammarForScopeName(final String scopeName) { return grammarForScopeName(scopeName, 0, null); } /** - * Get the grammar for `scopeName`. The grammar must first be created via - * `loadGrammar` or `loadGrammarFromPathSync`. + * Get the grammar for `scopeName`. + * The grammar must first be created via `loadGrammar` or `loadGrammarFromPathSync`. */ - public IGrammar grammarForScopeName(String scopeName, int initialLanguage, Map embeddedLanguages) { - return this.syncRegistry.grammarForScopeName(scopeName, initialLanguage, embeddedLanguages); + @Nullable + public IGrammar grammarForScopeName(final String scopeName, final int initialLanguage, + @Nullable final Map embeddedLanguages) { + return this.syncRegistry.grammarForScopeName(scopeName, initialLanguage, embeddedLanguages, /*TODO*/null, + /*TODO*/null); } public IRegistryOptions getLocator() { - return locator; + return options; } } diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/registry/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/registry/package-info.java new file mode 100644 index 000000000..1b343fe1f --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/registry/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.core.registry; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/ColorMap.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/ColorMap.java deleted file mode 100644 index 78130ce44..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/ColorMap.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.theme; - -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Set; - -public class ColorMap { - - private int lastColorId; - private final Map color2id; - - public ColorMap() { - this.lastColorId = 0; - this.color2id = new HashMap<>(); - } - - public int getId(String color) { - if (color == null) { - return 0; - } - color = color.toUpperCase(); - Integer value = this.color2id.get(color); - if (value != null) { - return value; - } - value = ++this.lastColorId; - this.color2id.put(color, value); - return value; - } - - public String getColor(int id) { - for (Entry entry : color2id.entrySet()) { - if (id == entry.getValue()) { - return entry.getKey(); - } - } - return null; - } - - public Set getColorMap() { - return this.color2id.keySet(); - } - - @Override - public int hashCode() { - return Objects.hash(color2id, lastColorId); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ColorMap other = (ColorMap) obj; - return Objects.equals(color2id, other.color2id) && lastColorId == other.lastColorId; - } - - -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/IRawThemeSetting.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/IRawThemeSetting.java deleted file mode 100644 index 587912c9e..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/IRawThemeSetting.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.theme; - -/** - * A single theme setting. - * - * @see https://github.com/Microsoft/vscode-textmate/blob/master/src/main.ts - */ -public interface IRawThemeSetting { - - String getName(); - - Object getScope(); - - IThemeSetting getSetting(); - -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/IStyle.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/IStyle.java index 3700a98ec..096caff31 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/IStyle.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/IStyle.java @@ -1,28 +1,32 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.theme; - -public interface IStyle { - - RGB getColor(); - - RGB getBackgroundColor(); - - boolean isBold(); - - boolean isItalic(); - - boolean isUnderline(); - - boolean isStrikeThrough(); - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.theme; + +import org.eclipse.jdt.annotation.Nullable; + +public interface IStyle { + + @Nullable + RGB getColor(); + + @Nullable + RGB getBackgroundColor(); + + boolean isBold(); + + boolean isItalic(); + + boolean isUnderline(); + + boolean isStrikeThrough(); + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/ParsedThemeRule.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/ParsedThemeRule.java deleted file mode 100644 index 6df2ee9d8..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/ParsedThemeRule.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.theme; - -import java.util.List; - -public class ParsedThemeRule { - - // _parsedThemeRuleBrand: void; - - public final String scope; - public final List parentScopes; - public final int index; - - /** - * -1 if not set. An or mask of `FontStyle` otherwise. - */ - public final int fontStyle; - public final String foreground; - public final String background; - - public ParsedThemeRule(String scope, List parentScopes, int index, int fontStyle, String foreground, - String background) { - this.scope = scope; - this.parentScopes = parentScopes; - this.index = index; - this.fontStyle = fontStyle; - this.foreground = foreground; - this.background = background; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((background == null) ? 0 : background.hashCode()); - result = prime * result + fontStyle; - result = prime * result + ((foreground == null) ? 0 : foreground.hashCode()); - result = prime * result + index; - result = prime * result + ((parentScopes == null) ? 0 : parentScopes.hashCode()); - result = prime * result + ((scope == null) ? 0 : scope.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - ParsedThemeRule other = (ParsedThemeRule) obj; - if (background == null) { - if (other.background != null) - return false; - } else if (!background.equals(other.background)) - return false; - if (fontStyle != other.fontStyle) - return false; - if (foreground == null) { - if (other.foreground != null) - return false; - } else if (!foreground.equals(other.foreground)) - return false; - if (index != other.index) - return false; - if (parentScopes == null) { - if (other.parentScopes != null) - return false; - } else if (!parentScopes.equals(other.parentScopes)) - return false; - if (scope == null) { - if (other.scope != null) - return false; - } else if (!scope.equals(other.scope)) - return false; - return true; - } - -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/RGB.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/RGB.java index be3926ec1..17a239684 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/RGB.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/RGB.java @@ -1,25 +1,25 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.theme; - -public class RGB { - - public final int red; - public final int green; - public final int blue; - - public RGB(int red, int green, int blue) { - this.red = red; - this.green = green; - this.blue = blue; - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.theme; + +public class RGB { + + public final int red; + public final int green; + public final int blue; + + public RGB(final int red, final int green, final int blue) { + this.red = red; + this.green = green; + this.blue = blue; + } +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/Theme.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/Theme.java deleted file mode 100644 index 1f0e857d3..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/Theme.java +++ /dev/null @@ -1,259 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.theme; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.regex.Pattern; - -import org.eclipse.tm4e.core.internal.utils.CompareUtils; - -/** - * TextMate theme. - * - */ -public class Theme { - - private static final Pattern rrggbb = Pattern.compile("^#[0-9a-f]{6}", Pattern.CASE_INSENSITIVE); - private static final Pattern rrggbbaa = Pattern.compile("^#[0-9a-f]{8}", Pattern.CASE_INSENSITIVE); - private static final Pattern rgb = Pattern.compile("^#[0-9a-f]{3}", Pattern.CASE_INSENSITIVE); - private static final Pattern rgba = Pattern.compile("^#[0-9a-f]{4}", Pattern.CASE_INSENSITIVE); - - private final ColorMap colorMap; - private final ThemeTrieElement root; - private final ThemeTrieElementRule defaults; - private final Map> cache; - - public static Theme createFromRawTheme(IRawTheme source) { - return createFromParsedTheme(parseTheme(source)); - } - - public static List parseTheme(IRawTheme source) { - if (source == null || source.getSettings() == null) { - return Collections.emptyList(); - } - // if (!source.settings || !Array.isArray(source.settings)) { - // return []; - // } - Collection settings = source.getSettings(); - List result = new ArrayList<>(); - int i = 0; - for (IRawThemeSetting entry : settings) { - - if (entry.getSetting() == null) { - continue; - } - - Object settingScope = entry.getScope(); - List scopes = new ArrayList<>(); - if (settingScope instanceof String) { - String scope = (String) settingScope; - - // remove leading commas - scope = scope.replaceAll("^[,]+", ""); - - // remove trailing commans - scope = scope.replaceAll("[,]+$", ""); - - scopes = Arrays.asList(scope.split(",")); - } else if (settingScope instanceof List) { - scopes = (List) settingScope; - } else { - scopes.add(""); - } - - int fontStyle = FontStyle.NotSet; - Object settingsFontStyle = entry.getSetting().getFontStyle(); - if (settingsFontStyle instanceof String) { - fontStyle = FontStyle.None; - - String[] segments = ((String) settingsFontStyle).split(" "); - for (String segment : segments) { - if ("italic".equals(segment)) { - fontStyle = fontStyle | FontStyle.Italic; - } else if ("bold".equals(segment)) { - fontStyle = fontStyle | FontStyle.Bold; - } else if ("underline".equals(segment)) { - fontStyle = fontStyle | FontStyle.Underline; - } - } - } - - String foreground = null; - Object settingsForeground = entry.getSetting().getForeground(); - if (settingsForeground instanceof String && isValidHexColor((String) settingsForeground)) { - foreground = (String) settingsForeground; - } - - String background = null; - Object settingsBackground = entry.getSetting().getBackground(); - if (settingsBackground instanceof String && isValidHexColor((String) settingsBackground)) { - background = (String) settingsBackground; - } - for (int j = 0, lenJ = scopes.size(); j < lenJ; j++) { - String _scope = scopes.get(j).trim(); - - List segments = Arrays.asList(_scope.split(" ")); - - String scope = segments.get(segments.size() - 1); - List parentScopes = null; - if (segments.size() > 1) { - parentScopes = segments.subList(0, segments.size() - 1);// slice(0, - // segments.length - // - - // 1); - Collections.reverse(parentScopes); // parentScopes.reverse(); - } - - ParsedThemeRule t = new ParsedThemeRule(scope, parentScopes, i, fontStyle, foreground, background); - result.add(t); - } - i++; - } - - return result; - } - - private static boolean isValidHexColor(String hex) { - if (hex == null || hex.length() < 1) { - return false; - } - - if (rrggbb.matcher(hex).matches()) { - // #rrggbb - return true; - } - - if (rrggbbaa.matcher(hex).matches()) { - // #rrggbbaa - return true; - } - - if (rgb.matcher(hex).matches()) { - // #rgb - return true; - } - - if (rgba.matcher(hex).matches()) { - // #rgba - return true; - } - - return false; - } - - public static Theme createFromParsedTheme(List source) { - return resolveParsedThemeRules(source); - } - - /** - * Resolve rules (i.e. inheritance). - */ - public static Theme resolveParsedThemeRules(List parsedThemeRules) { - // Sort rules lexicographically, and then by index if necessary - parsedThemeRules.sort((a, b) -> { - int r = CompareUtils.strcmp(a.scope, b.scope); - if (r != 0) { - return r; - } - r = CompareUtils.strArrCmp(a.parentScopes, b.parentScopes); - if (r != 0) { - return r; - } - return a.index - b.index; - }); - - // Determine defaults - int defaultFontStyle = FontStyle.None; - String defaultForeground = "#000000"; - String defaultBackground = "#ffffff"; - while (parsedThemeRules.size() >= 1 && "".equals(parsedThemeRules.get(0).scope)) { - ParsedThemeRule incomingDefaults = parsedThemeRules.remove(0); // shift(); - if (incomingDefaults.fontStyle != FontStyle.NotSet) { - defaultFontStyle = incomingDefaults.fontStyle; - } - if (incomingDefaults.foreground != null) { - defaultForeground = incomingDefaults.foreground; - } - if (incomingDefaults.background != null) { - defaultBackground = incomingDefaults.background; - } - } - ColorMap colorMap = new ColorMap(); - ThemeTrieElementRule defaults = new ThemeTrieElementRule(0, null, defaultFontStyle, - colorMap.getId(defaultForeground), colorMap.getId(defaultBackground)); - - ThemeTrieElement root = new ThemeTrieElement(new ThemeTrieElementRule(0, null, FontStyle.NotSet, 0, 0), - Collections.emptyList()); - for (ParsedThemeRule rule : parsedThemeRules) { - root.insert(0, rule.scope, rule.parentScopes, rule.fontStyle, colorMap.getId(rule.foreground), - colorMap.getId(rule.background)); - } - - return new Theme(colorMap, defaults, root); - } - - public Theme(ColorMap colorMap, ThemeTrieElementRule defaults, ThemeTrieElement root) { - this.colorMap = colorMap; - this.root = root; - this.defaults = defaults; - this.cache = new HashMap<>(); - } - - public Set getColorMap() { - return this.colorMap.getColorMap(); - } - - public String getColor(int id) { - return this.colorMap.getColor(id); - } - - public ThemeTrieElementRule getDefaults() { - return this.defaults; - } - - public List match(String scopeName) { - if (!this.cache.containsKey(scopeName)) { - this.cache.put(scopeName, this.root.match(scopeName)); - } - return this.cache.get(scopeName); - } - - @Override - public int hashCode() { - return Objects.hash(cache, colorMap, defaults, root); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Theme other = (Theme) obj; - return Objects.equals(cache, other.cache) && Objects.equals(colorMap, other.colorMap) && - Objects.equals(defaults, other.defaults) && Objects.equals(root, other.root); - } - -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/CSSParser.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/CSSParser.java index 31d98232a..88ff3f98c 100644 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/CSSParser.java +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/CSSParser.java @@ -1,90 +1,94 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.theme.css; - -import java.io.IOException; -import java.io.InputStream; -import java.io.StringReader; -import java.util.List; - -import org.eclipse.tm4e.core.internal.css.CSSConditionFactory; -import org.eclipse.tm4e.core.internal.css.CSSDocumentHandler; -import org.eclipse.tm4e.core.internal.css.CSSSelectorFactory; -import org.eclipse.tm4e.core.internal.css.ExtendedSelector; -import org.eclipse.tm4e.core.theme.IStyle; -import org.w3c.css.sac.CSSException; -import org.w3c.css.sac.InputSource; -import org.w3c.css.sac.Parser; -import org.w3c.css.sac.Selector; -import org.w3c.css.sac.SelectorList; - -/** - * CSS Parser to parse style for TextMate syntax coloration. - * - */ -public class CSSParser { - - private final CSSDocumentHandler handler; - - public CSSParser(InputStream source) throws Exception { - this(toSource(source)); - } - - private static InputSource toSource(InputStream source) { - InputSource in = new InputSource(); - in.setByteStream(source); - return in; - } - - public CSSParser(InputSource source) throws Exception { - this(source, SACParserFactory.newInstance().makeParser()); - } - - public CSSParser(String source) throws Exception { - this(new InputSource(new StringReader(source))); - } - - public CSSParser(InputSource source, Parser parser) throws CSSException, IOException { - this.handler = new CSSDocumentHandler(); - parser.setDocumentHandler(handler); - parser.setConditionFactory(CSSConditionFactory.INSTANCE); - parser.setSelectorFactory(CSSSelectorFactory.INSTANCE); - parser.parseStyleSheet(source); - } - - public IStyle getBestStyle(String... names) { - int bestSpecificity = 0; - IStyle bestStyle = null; - for (IStyle style : handler.getList()) { - SelectorList list = ((CSSStyle) style).getSelectorList(); - for (int i = 0; i < list.getLength(); i++) { - Selector selector = list.item(i); - if (selector instanceof ExtendedSelector) { - ExtendedSelector s = ((ExtendedSelector) selector); - int nbMatch = s.nbMatch(names); - if (nbMatch > 0 && nbMatch == s.nbClass()) { - if (bestStyle == null || (nbMatch >= bestSpecificity)) { - bestStyle = style; - bestSpecificity = nbMatch; - } - } - } - } - } - return bestStyle; - } - - public List getStyles() { - return handler.getList(); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.theme.css; + +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.internal.theme.css.CSSConditionFactory; +import org.eclipse.tm4e.core.internal.theme.css.CSSDocumentHandler; +import org.eclipse.tm4e.core.internal.theme.css.CSSSelectorFactory; +import org.eclipse.tm4e.core.internal.theme.css.CSSStyle; +import org.eclipse.tm4e.core.internal.theme.css.ExtendedSelector; +import org.eclipse.tm4e.core.internal.theme.css.sac.SACParserFactory; +import org.eclipse.tm4e.core.theme.IStyle; +import org.w3c.css.sac.CSSException; +import org.w3c.css.sac.InputSource; +import org.w3c.css.sac.Parser; +import org.w3c.css.sac.Selector; +import org.w3c.css.sac.SelectorList; + +/** + * CSS Parser to parse style for TextMate syntax coloring. + * + */ +public class CSSParser { + + private final CSSDocumentHandler handler; + + public CSSParser(final InputStream source) throws Exception { + this(toSource(source)); + } + + private static InputSource toSource(final InputStream source) { + final InputSource in = new InputSource(); + in.setByteStream(source); + return in; + } + + public CSSParser(final InputSource source) throws Exception { + this(source, new SACParserFactory().makeParser()); + } + + public CSSParser(final String source) throws Exception { + this(new InputSource(new StringReader(source))); + } + + public CSSParser(final InputSource source, final Parser parser) throws CSSException, IOException { + this.handler = new CSSDocumentHandler(); + parser.setDocumentHandler(handler); + parser.setConditionFactory(CSSConditionFactory.INSTANCE); + parser.setSelectorFactory(CSSSelectorFactory.INSTANCE); + parser.parseStyleSheet(source); + } + + @Nullable + public IStyle getBestStyle(final String... names) { + int bestSpecificity = 0; + IStyle bestStyle = null; + for (final IStyle style : handler.getList()) { + final SelectorList list = ((CSSStyle) style).getSelectorList(); + for (int i = 0; i < list.getLength(); i++) { + final Selector selector = list.item(i); + if (selector instanceof ExtendedSelector) { + final ExtendedSelector s = ((ExtendedSelector) selector); + final int nbMatch = s.nbMatch(names); + if (nbMatch > 0 && nbMatch == s.nbClass()) { + if (bestStyle == null || (nbMatch >= bestSpecificity)) { + bestStyle = style; + bestSpecificity = nbMatch; + } + } + } + } + } + return bestStyle; + } + + public List getStyles() { + return handler.getList(); + } + +} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/ISACParserFactory.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/ISACParserFactory.java deleted file mode 100644 index 8768bfac0..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/ISACParserFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008, 2013 Angelo Zerr and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Angelo Zerr - initial API and implementation - *******************************************************************************/ -package org.eclipse.tm4e.core.theme.css; - -import org.w3c.css.sac.Parser; - -/** - * SAC parser factory interface to get instance of SAC {@link Parser}. - */ -public interface ISACParserFactory { - - /** - * Return default instance of SAC Parser. If preferredParserName is filled, - * it return the instance of SAC Parser registered with this name, otherwise - * this method search teh SAC Parser class name to instanciate into System - * property with key org.w3c.css.sac.parser. - */ - public Parser makeParser() throws ClassNotFoundException, - IllegalAccessException, InstantiationException, - NullPointerException, ClassCastException; - - /** - * Return instance of SAC Parser registered into the factory with name - * name. - * - * @param name - * @return - * @throws ClassNotFoundException - * @throws IllegalAccessException - * @throws InstantiationException - * @throws NullPointerException - * @throws ClassCastException - */ - public abstract Parser makeParser(String name) - throws ClassNotFoundException, IllegalAccessException, - InstantiationException, NullPointerException, ClassCastException; -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/ParserNotFoundException.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/ParserNotFoundException.java deleted file mode 100644 index e80f95d56..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/ParserNotFoundException.java +++ /dev/null @@ -1,24 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008, 2013 Angelo Zerr and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Angelo Zerr - initial API and implementation - * IBM Corporation - ongoing development - *******************************************************************************/ -package org.eclipse.tm4e.core.theme.css; - -/** - * Exception used when SAC parser is not retrieved. - */ -public class ParserNotFoundException extends RuntimeException { - - private static final long serialVersionUID = 4339161134287845644L; - - public ParserNotFoundException(Throwable throwable) { - super(throwable); - } -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/SACParserFactory.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/SACParserFactory.java deleted file mode 100644 index a4c3c9b0b..000000000 --- a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/SACParserFactory.java +++ /dev/null @@ -1,92 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008, 2014 Angelo Zerr and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Angelo Zerr - initial API and implementation - *******************************************************************************/ -package org.eclipse.tm4e.core.theme.css; - -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.eclipse.tm4e.core.internal.css.SACParserFactoryImpl; -import org.w3c.css.sac.Parser; -import org.w3c.css.sac.helpers.ParserFactory; - -/** - * SAC Parser Factory. - */ -public abstract class SACParserFactory extends ParserFactory implements ISACParserFactory { - - private static final Logger LOGGER = Logger.getLogger(SACParserFactory.class.getName()); - - private String preferredParserName; - - /** - * Return default instance of SAC Parser. If preferredParserName is filled, - * it return the instance of SAC Parser registered with this name, otherwise - * this method search the SAC Parser class name to instanciate into System - * property with key org.w3c.css.sac.parser. - */ - @Override - public Parser makeParser() throws ClassNotFoundException, IllegalAccessException, InstantiationException, - NullPointerException, ClassCastException { - try { - if (preferredParserName != null) { - return makeParser(preferredParserName); - } - } catch (Throwable e) { - LOGGER.log(Level.SEVERE, e.getMessage(), e); - } - return super.makeParser(); - } - - /** - * Return preferred SAC parser name if it is filled and null otherwise. - * - * @return - */ - public String getPreferredParserName() { - return preferredParserName; - } - - /** - * Set the preferred SAC parser name to use when makeParser is called. - * - * @param preferredParserName - */ - public void setPreferredParserName(String preferredParserName) { - this.preferredParserName = preferredParserName; - } - - /** - * Return instance of SACParserFactory - * - * @return - */ - public static ISACParserFactory newInstance() { - // TODO : manage new instance of SAC Parser Factory like - // SAXParserFactory. - return new SACParserFactoryImpl(); - } - - /** - * Return instance of SAC Parser registered into the factory with name - * name. - * - * @param name - * @return - * @throws ClassNotFoundException - * @throws IllegalAccessException - * @throws InstantiationException - * @throws NullPointerException - * @throws ClassCastException - */ - @Override - public abstract Parser makeParser(String name) throws ClassNotFoundException, IllegalAccessException, - InstantiationException, NullPointerException, ClassCastException; -} diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/package-info.java new file mode 100644 index 000000000..fc68ac204 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/css/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.core.theme.css; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/package-info.java b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/package-info.java new file mode 100644 index 000000000..4401cf1c8 --- /dev/null +++ b/org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/theme/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.core.theme; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/Data.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/Data.java index 7eb0ddfa8..66d2bb555 100644 --- a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/Data.java +++ b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/Data.java @@ -1,16 +1,16 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core; - -public class Data { - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core; + +public class Data { + +} diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/OnigStringTest.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/OnigStringTest.java deleted file mode 100644 index 4cf0bc62a..000000000 --- a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/OnigStringTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.eclipse.tm4e.core; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.fail; - -import org.eclipse.tm4e.core.internal.oniguruma.OnigString; -import org.junit.jupiter.api.Test; - -public class OnigStringTest { - - @Test - public void testUtf8Utf16Conversions() { - OnigString onigString = new OnigString("áé"); - assertEquals(onigString.utf8_value.length, 4); - assertEquals(onigString.string.length(), 2); - assertEquals(onigString.convertUtf8OffsetToUtf16(0), 0); - } - - @Test - public void testUtf8Utf16Conversions2() { - - String string = "myááçóúôõaab"; - OnigString utf8WithCharLen = new OnigString(string); - - assertEquals(0, utf8WithCharLen.convertUtf16OffsetToUtf8(0)); - assertEquals(1, utf8WithCharLen.convertUtf16OffsetToUtf8(1)); - assertEquals(2, utf8WithCharLen.convertUtf16OffsetToUtf8(2)); - assertEquals(4, utf8WithCharLen.convertUtf16OffsetToUtf8(3)); - assertEquals(6, utf8WithCharLen.convertUtf16OffsetToUtf8(4)); - assertEquals(8, utf8WithCharLen.convertUtf16OffsetToUtf8(5)); - assertEquals(10, utf8WithCharLen.convertUtf16OffsetToUtf8(6)); - assertEquals(12, utf8WithCharLen.convertUtf16OffsetToUtf8(7)); - try { - utf8WithCharLen.convertUtf16OffsetToUtf8(55); - fail("Expected error"); - } catch (ArrayIndexOutOfBoundsException e) { - } - - assertEquals(0, utf8WithCharLen.convertUtf8OffsetToUtf16(0)); - assertEquals(1, utf8WithCharLen.convertUtf8OffsetToUtf16(1)); - assertEquals(2, utf8WithCharLen.convertUtf8OffsetToUtf16(2)); - assertEquals(2, utf8WithCharLen.convertUtf8OffsetToUtf16(3)); - assertEquals(3, utf8WithCharLen.convertUtf8OffsetToUtf16(4)); - assertEquals(3, utf8WithCharLen.convertUtf8OffsetToUtf16(5)); - assertEquals(4, utf8WithCharLen.convertUtf8OffsetToUtf16(6)); - assertEquals(4, utf8WithCharLen.convertUtf8OffsetToUtf16(7)); - assertEquals(5, utf8WithCharLen.convertUtf8OffsetToUtf16(8)); - assertEquals(6, utf8WithCharLen.convertUtf8OffsetToUtf16(10)); - assertEquals(7, utf8WithCharLen.convertUtf8OffsetToUtf16(12)); - try { - utf8WithCharLen.convertUtf8OffsetToUtf16(55); - fail("Expected error"); - } catch (ArrayIndexOutOfBoundsException e) { - } - - } -} diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/TestGrammar.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/TestGrammar.java index d30bbef31..d2c4b2d12 100644 --- a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/TestGrammar.java +++ b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/TestGrammar.java @@ -1,31 +1,33 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core; - -import org.eclipse.tm4e.core.grammar.IGrammar; -import org.eclipse.tm4e.core.grammar.ITokenizeLineResult; -import org.eclipse.tm4e.core.registry.Registry; - -public class TestGrammar { - - public static void main(String[] args) throws Exception { - - Registry registry = new Registry(); - IGrammar grammar = registry.loadGrammarFromPathSync("Angular2TypeScript.tmLanguage", - TestGrammar.class.getResourceAsStream("Angular2TypeScript.tmLanguage")); - - ITokenizeLineResult result = grammar.tokenizeLine("/** **/"); - for (int i = 0; i < result.getTokens().length; i++) { - System.err.println(result.getTokens()[i]); - } - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import org.eclipse.tm4e.core.grammar.IGrammar; +import org.eclipse.tm4e.core.grammar.ITokenizeLineResult; +import org.eclipse.tm4e.core.registry.Registry; + +public class TestGrammar { + + public static void main(String[] args) throws Exception { + + Registry registry = new Registry(); + IGrammar grammar = castNonNull(registry.loadGrammarFromPathSync("Angular2TypeScript.tmLanguage", + TestGrammar.class.getResourceAsStream("Angular2TypeScript.tmLanguage"))); + + ITokenizeLineResult result = grammar.tokenizeLine("/** **/"); + for (int i = 0; i < result.getTokens().length; i++) { + System.err.println(result.getTokens()[i]); + } + } +} diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/TestOngurama.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/TestOngurama.java deleted file mode 100644 index de601a35b..000000000 --- a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/TestOngurama.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core; - -import org.eclipse.tm4e.core.internal.oniguruma.IOnigNextMatchResult; -import org.eclipse.tm4e.core.internal.oniguruma.OnigScanner; - -public class TestOngurama { - - public static void main(String[] args) { - - OnigScanner scanner = new OnigScanner(new String[] { "c", "a(b)?" }); - IOnigNextMatchResult result = scanner.findNextMatchSync("abc", 0); - System.err.println(result); - - scanner = new OnigScanner(new String[] { "a([b-d])c" }); - result = scanner.findNextMatchSync("!abcdef", 0); - System.err.println(result); - } -} diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/benchmark/BenchmarkRunner.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/benchmark/BenchmarkRunner.java new file mode 100644 index 000000000..021fc3a5c --- /dev/null +++ b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/benchmark/BenchmarkRunner.java @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2022 Sebastian Thomschke and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.tm4e.core.benchmark; + +import java.lang.management.ManagementFactory; +import java.util.Locale; + +public final class BenchmarkRunner { + + private static final Runtime RUNTIME = Runtime.getRuntime(); + private static final String SEPARATOR = "--------------------------------"; + + public static void run(final int warmUpRounds, final int benchmarkRounds, final int opsPerBenchmarkRound, + final Runnable benchmark) throws InterruptedException { + Locale.setDefault(Locale.ENGLISH); + System.out.println("JVM Vendor: " + System.getProperty("java.vendor")); + System.out.println("JVM Version: " + System.getProperty("java.version")); + System.out.println(String.format("JVM Inital Heap: %.2f MB", RUNTIME.maxMemory() / (float) 1024 / 1024)); + System.out.println(String.format("JVM Maximum Heap: %.2f MB", RUNTIME.totalMemory() / (float) 1024 / 1024)); + System.out.println("JVM Args: " + String.join(" ", ManagementFactory.getRuntimeMXBean().getInputArguments())); + System.out.println(SEPARATOR); + + System.out.println("Warmup Rounds: " + warmUpRounds); + System.out.println("Benchmark Rounds: " + warmUpRounds); + System.out.println("Operations per Benchmark Round: " + opsPerBenchmarkRound); + System.out.println(SEPARATOR); + + // warmup + for (int r = 1; r <= warmUpRounds; r++) { + runRound("warm-up", r, warmUpRounds, + 5 * opsPerBenchmarkRound, // use more iterations to force JIT to kick in + false, // don't try to measure heap usage as warm-up rounds will trigger gc + benchmark); + } + + System.out.println(SEPARATOR); + + // benchmark + for (int r = 1; r <= benchmarkRounds; r++) { + runRound("benchmark", r, benchmarkRounds, + opsPerBenchmarkRound, + true, + benchmark); + } + System.out.println("DONE."); + } + + private static void runRound(final String label, final int round, final int totalRounds, final int iterations, + final boolean measureHeapUsage, + final Runnable benchmark) throws InterruptedException { + // spinning up a thread so the JVM hopefully runs the benchmark on different cores each round + final var t = new Thread(() -> { + System.out.println(label + " " + round + "/" + totalRounds + "..."); + if (measureHeapUsage) { + try { + System.gc(); + Thread.sleep(1_000); + System.gc(); + Thread.sleep(1_000); + } catch (final InterruptedException ex) { + Thread.interrupted(); + throw new RuntimeException(ex); + } + } + + final var startFreeMem = RUNTIME.freeMemory(); + final var startAt = System.currentTimeMillis(); + + for (int i = 0; i < iterations; i++) { + benchmark.run(); + } + + final var durationMS = System.currentTimeMillis() - startAt; + final var durationMSPerIteration = durationMS / (float) iterations; + final var iterationsPerSecond = 60_000 / durationMSPerIteration; + + if (measureHeapUsage) { + final var heapBytesPerIteration = (startFreeMem - RUNTIME.freeMemory()) + / (float) iterations; + System.out.println(String.format( + " -> result: %,5d ms/round | %,7.2f ops/s | %,5.2f ms/op | %,6.3f MB/op", + durationMS, + iterationsPerSecond, + durationMSPerIteration, + heapBytesPerIteration / 1024 / 1024)); + } else { + System.out.println(String.format( + " -> result: %,5d ms/round | %,7.2f ops/s | %,5.2f ms/op", + durationMS, + iterationsPerSecond, + durationMSPerIteration)); + } + }); + t.setPriority(Thread.MAX_PRIORITY); + t.run(); + t.join(); + } +} \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/benchmark/GrammarBenchmark.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/benchmark/GrammarBenchmark.java new file mode 100644 index 000000000..47d9e5399 --- /dev/null +++ b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/benchmark/GrammarBenchmark.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2022 Sebastian Thomschke and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.tm4e.core.benchmark; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; + +import org.eclipse.tm4e.core.grammar.IGrammar; +import org.eclipse.tm4e.core.grammar.IStackElement; +import org.eclipse.tm4e.core.registry.Registry; + +public final class GrammarBenchmark implements Runnable { + + private static final int WARMUP_ROUNDS = 3; + private static final int BENCHMARK_ROUNDS = 3; + private static final int OPS_PER_BENCHMARK_ROUND = 50; + + public static void main(final String... args) throws Exception { + BenchmarkRunner.run(WARMUP_ROUNDS, BENCHMARK_ROUNDS, OPS_PER_BENCHMARK_ROUND, new GrammarBenchmark()); + } + + final IGrammar grammar; + final String[] sourceCode; + + GrammarBenchmark() throws Exception { + /* + * load the grammar + */ + try (var grammarFileIS = GrammarBenchmark.class.getResourceAsStream("GrammarBenchmark.Java.tmLanguage.json")) { + grammar = new Registry().loadGrammarFromPathSync("GrammarBenchmark.Java.tmLanguage.json", grammarFileIS); + } + + /* + * load the file to be parsed + */ + try (var sourceFileIS = GrammarBenchmark.class.getResourceAsStream("GrammarBenchmark.JavaFile.txt")) { + sourceCode = new BufferedReader(new InputStreamReader(sourceFileIS, StandardCharsets.UTF_8)) + .lines() + .toArray(String[]::new); + } + System.out.println( + String.format("Source Code chars: %,d", Arrays.stream(sourceCode).mapToInt(String::length).sum())); + System.out.println(String.format("Source Code lines: %,d", sourceCode.length)); + } + + /** + * Tokenize all lines of the pre-loaded source file + */ + @Override + public void run() { + IStackElement state = null; + for (final var line : sourceCode) { + state = grammar.tokenizeLine(line, state).getRuleStack(); + } + } +} \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/GrammarInjectionTest.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/GrammarInjectionTest.java index 69885692b..c502ccef6 100644 --- a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/GrammarInjectionTest.java +++ b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/GrammarInjectionTest.java @@ -1,85 +1,93 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.grammar; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Collection; - -import org.eclipse.tm4e.core.Data; -import org.eclipse.tm4e.core.registry.IRegistryOptions; -import org.eclipse.tm4e.core.registry.Registry; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -/** - * Test for grammar tokenizer. - * - */ -public class GrammarInjectionTest { - - private static final String[] EXPECTED_TOKENS = { - "Token from 0 to 1 with scopes [source.ts, meta.decorator.ts, punctuation.decorator.ts]", - "Token from 1 to 10 with scopes [source.ts, meta.decorator.ts, entity.name.function.ts]", - "Token from 10 to 11 with scopes [source.ts, meta.decorator.ts, meta.brace.round.ts]", - "Token from 11 to 12 with scopes [source.ts, meta.decorator.ts, meta.object-literal.ts, punctuation.definition.block.ts]", - "Token from 12 to 20 with scopes [source.ts, meta.decorator.ts, meta.object-literal.ts, meta.object.member.ts, meta.object-literal.key.ts]", - "Token from 20 to 21 with scopes [source.ts, meta.decorator.ts, meta.object-literal.ts, meta.object.member.ts, meta.object-literal.key.ts, punctuation.separator.key-value.ts]", - "Token from 21 to 22 with scopes [source.ts, meta.decorator.ts, meta.object-literal.ts, meta.object.member.ts, string.template.ts, punctuation.definition.string.template.begin.ts]", - "Token from 22 to 38 with scopes [source.ts, meta.decorator.ts, meta.object-literal.ts, meta.object.member.ts, string.template.ts]", - "Token from 38 to 39 with scopes [source.ts, meta.decorator.ts, meta.object-literal.ts, meta.object.member.ts, string.template.ts, punctuation.definition.string.template.end.ts]", - "Token from 39 to 40 with scopes [source.ts, meta.decorator.ts, meta.object-literal.ts, punctuation.definition.block.ts]", - "Token from 40 to 41 with scopes [source.ts, meta.decorator.ts, meta.brace.round.ts]" }; - - - @Test - public void angular2TokenizeLine() throws Exception { - Registry registry = new Registry(new IRegistryOptions() { - - @Override - public InputStream getInputStream(String scopeName) throws IOException { - return Data.class.getResourceAsStream(getFilePath(scopeName)); - } - - @Override - public Collection getInjections(String scopeName) { - return Arrays.asList("template.ng", "styles.ng"); - } - - @Override - public String getFilePath(String scopeName) { - if ("source.js".equals(scopeName)) { - return "JavaScript.tmLanguage.json"; - } else if ("text.html.basic".equals(scopeName)) { - return "html.json"; - } else if ("source.ts".equals(scopeName)) { - return "TypeScript.tmLanguage.json"; - } else if ("template.ng".equals(scopeName)) { - return "template.ng.json"; - } else if ("styles.ng".equals(scopeName)) { - return "styles.ng.json"; - } - return null; - } - }); - IGrammar grammar = registry.loadGrammar("source.ts"); - ITokenizeLineResult lineTokens = grammar.tokenizeLine("@Component({template:``})"); - for (int i = 0; i < lineTokens.getTokens().length; i++) { - IToken token = lineTokens.getTokens()[i]; - String s = "Token from " + token.getStartIndex() + " to " + token.getEndIndex() + " with scopes " - + token.getScopes(); - System.err.println(s); - Assertions.assertEquals(EXPECTED_TOKENS[i], s); - } - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.grammar; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Collection; +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.Data; +import org.eclipse.tm4e.core.registry.IRegistryOptions; +import org.eclipse.tm4e.core.registry.Registry; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * Test for grammar tokenizer. + * + */ +public class GrammarInjectionTest { + + private static final String[] EXPECTED_TOKENS = { + "Token from 0 to 1 with scopes [source.ts, meta.decorator.ts, punctuation.decorator.ts]", + "Token from 1 to 10 with scopes [source.ts, meta.decorator.ts, entity.name.function.ts]", + "Token from 10 to 11 with scopes [source.ts, meta.decorator.ts, meta.brace.round.ts]", + "Token from 11 to 12 with scopes [source.ts, meta.decorator.ts, meta.object-literal.ts, punctuation.definition.block.ts]", + "Token from 12 to 20 with scopes [source.ts, meta.decorator.ts, meta.object-literal.ts, meta.object.member.ts, meta.object-literal.key.ts]", + "Token from 20 to 21 with scopes [source.ts, meta.decorator.ts, meta.object-literal.ts, meta.object.member.ts, meta.object-literal.key.ts, punctuation.separator.key-value.ts]", + "Token from 21 to 22 with scopes [source.ts, meta.decorator.ts, meta.object-literal.ts, meta.object.member.ts, string.template.ts, punctuation.definition.string.template.begin.ts]", + "Token from 22 to 38 with scopes [source.ts, meta.decorator.ts, meta.object-literal.ts, meta.object.member.ts, string.template.ts]", + "Token from 38 to 39 with scopes [source.ts, meta.decorator.ts, meta.object-literal.ts, meta.object.member.ts, string.template.ts, punctuation.definition.string.template.end.ts]", + "Token from 39 to 40 with scopes [source.ts, meta.decorator.ts, meta.object-literal.ts, punctuation.definition.block.ts]", + "Token from 40 to 41 with scopes [source.ts, meta.decorator.ts, meta.brace.round.ts]" }; + + @Test + public void angular2TokenizeLine() throws Exception { + Registry registry = new Registry(new IRegistryOptions() { + + @Nullable + @Override + public InputStream getInputStream(@Nullable String scopeName) throws IOException { + return Data.class.getResourceAsStream(getFilePath(scopeName)); + } + + @Nullable + @Override + public Collection getInjections(@Nullable String scopeName) { + return List.of("template.ng", "styles.ng"); + } + + @Nullable + @Override + public String getFilePath(@Nullable String scopeName) { + if (scopeName != null) { + switch (scopeName) { + case "source.js": + return "JavaScript.tmLanguage.json"; + case "text.html.basic": + return "html.json"; + case "source.ts": + return "TypeScript.tmLanguage.json"; + case "template.ng": + return "template.ng.json"; + case "styles.ng": + return "styles.ng.json"; + } + } + return null; + } + }); + IGrammar grammar = registry.loadGrammar("source.ts"); + final var lineTokens = castNonNull(grammar).tokenizeLine("@Component({template:``})"); + for (int i = 0; i < lineTokens.getTokens().length; i++) { + IToken token = lineTokens.getTokens()[i]; + String s = "Token from " + token.getStartIndex() + " to " + token.getEndIndex() + " with scopes " + + token.getScopes(); + System.err.println(s); + Assertions.assertEquals(EXPECTED_TOKENS[i], s); + } + } +} diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/GrammarTest.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/GrammarTest.java index 8dc2fcb38..e1606a8f5 100644 --- a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/GrammarTest.java +++ b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/GrammarTest.java @@ -1,97 +1,99 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.grammar; - -import org.eclipse.tm4e.core.Data; -import org.eclipse.tm4e.core.registry.Registry; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -/** - * Test for grammar tokenizer. - * - */ -public class GrammarTest { - - private static final String[] EXPECTED_TOKENS = { - "Token from 0 to 8 with scopes [source.js, meta.function.js, storage.type.function.js]", - "Token from 8 to 9 with scopes [source.js, meta.function.js]", - "Token from 9 to 12 with scopes [source.js, meta.function.js, entity.name.function.js]", - "Token from 12 to 13 with scopes [source.js, meta.function.js, meta.function.type.parameter.js, meta.brace.round.js]", - "Token from 13 to 14 with scopes [source.js, meta.function.js, meta.function.type.parameter.js, parameter.name.js, variable.parameter.js]", - "Token from 14 to 15 with scopes [source.js, meta.function.js, meta.function.type.parameter.js]", - "Token from 15 to 16 with scopes [source.js, meta.function.js, meta.function.type.parameter.js, parameter.name.js, variable.parameter.js]", - "Token from 16 to 17 with scopes [source.js, meta.function.js, meta.function.type.parameter.js, meta.brace.round.js]", - "Token from 17 to 18 with scopes [source.js, meta.function.js]", - "Token from 18 to 19 with scopes [source.js, meta.function.js, meta.decl.block.js, meta.brace.curly.js]", - "Token from 19 to 20 with scopes [source.js, meta.function.js, meta.decl.block.js]", - "Token from 20 to 26 with scopes [source.js, meta.function.js, meta.decl.block.js, keyword.control.js]", - "Token from 26 to 28 with scopes [source.js, meta.function.js, meta.decl.block.js]", - "Token from 28 to 29 with scopes [source.js, meta.function.js, meta.decl.block.js, keyword.operator.arithmetic.js]", - "Token from 29 to 32 with scopes [source.js, meta.function.js, meta.decl.block.js]", - "Token from 32 to 33 with scopes [source.js, meta.function.js, meta.decl.block.js, meta.brace.curly.js]" }; - - private static final String[] EXPECTED_MULTI_LINE_TOKENS = { - "Token from 0 to 8 with scopes [source.js, meta.function.js, storage.type.function.js]", - "Token from 8 to 9 with scopes [source.js, meta.function.js]", - "Token from 9 to 12 with scopes [source.js, meta.function.js, entity.name.function.js]", - "Token from 12 to 13 with scopes [source.js, meta.function.js, meta.function.type.parameter.js, meta.brace.round.js]", - "Token from 13 to 14 with scopes [source.js, meta.function.js, meta.function.type.parameter.js, parameter.name.js, variable.parameter.js]", - "Token from 14 to 15 with scopes [source.js, meta.function.js, meta.function.type.parameter.js]", - "Token from 15 to 16 with scopes [source.js, meta.function.js, meta.function.type.parameter.js, parameter.name.js, variable.parameter.js]", - "Token from 16 to 17 with scopes [source.js, meta.function.js, meta.function.type.parameter.js, meta.brace.round.js]", - "Token from 0 to 1 with scopes [source.js, meta.function.js, meta.decl.block.js, meta.brace.curly.js]", - "Token from 1 to 2 with scopes [source.js, meta.function.js, meta.decl.block.js]", - "Token from 2 to 8 with scopes [source.js, meta.function.js, meta.decl.block.js, keyword.control.js]", - "Token from 8 to 10 with scopes [source.js, meta.function.js, meta.decl.block.js]", - "Token from 10 to 11 with scopes [source.js, meta.function.js, meta.decl.block.js, keyword.operator.arithmetic.js]", - "Token from 11 to 14 with scopes [source.js, meta.function.js, meta.decl.block.js]", - "Token from 14 to 15 with scopes [source.js, meta.function.js, meta.decl.block.js, meta.brace.curly.js]" }; - - @Test - public void tokenizeLine() throws Exception { - Registry registry = new Registry(); - String path = "JavaScript.tmLanguage"; - IGrammar grammar = registry.loadGrammarFromPathSync(path, Data.class.getResourceAsStream(path)); - ITokenizeLineResult lineTokens = grammar.tokenizeLine("function add(a,b) { return a+b; }"); - for (int i = 0; i < lineTokens.getTokens().length; i++) { - IToken token = lineTokens.getTokens()[i]; - String s = "Token from " + token.getStartIndex() + " to " + token.getEndIndex() + " with scopes " - + token.getScopes(); - Assertions.assertEquals(EXPECTED_TOKENS[i], s); - } - } - - @Test - public void tokenizeLines() throws Exception { - Registry registry = new Registry(); - String path = "JavaScript.tmLanguage"; - IGrammar grammar = registry.loadGrammarFromPathSync(path, Data.class.getResourceAsStream(path)); - - StackElement ruleStack = null; - int i = 0; - int j = 0; - String[] lines = { "function add(a,b)", "{ return a+b; }" }; - for (int l = 0; l < lines.length; l++) { - ITokenizeLineResult lineTokens = grammar.tokenizeLine(lines[l], ruleStack); - ruleStack = lineTokens.getRuleStack(); - for (i = 0; i < lineTokens.getTokens().length; i++) { - IToken token = lineTokens.getTokens()[i]; - String s = "Token from " + token.getStartIndex() + " to " + token.getEndIndex() + " with scopes " - + token.getScopes(); - Assertions.assertEquals(EXPECTED_MULTI_LINE_TOKENS[i + j], s); - } - j = i; - } - - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.grammar; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import org.eclipse.tm4e.core.Data; +import org.eclipse.tm4e.core.registry.Registry; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * Test for grammar tokenizer. + * + */ +public class GrammarTest { + + private static final String[] EXPECTED_TOKENS = { + "Token from 0 to 8 with scopes [source.js, meta.function.js, storage.type.function.js]", + "Token from 8 to 9 with scopes [source.js, meta.function.js]", + "Token from 9 to 12 with scopes [source.js, meta.function.js, entity.name.function.js]", + "Token from 12 to 13 with scopes [source.js, meta.function.js, meta.function.type.parameter.js, meta.brace.round.js]", + "Token from 13 to 14 with scopes [source.js, meta.function.js, meta.function.type.parameter.js, parameter.name.js, variable.parameter.js]", + "Token from 14 to 15 with scopes [source.js, meta.function.js, meta.function.type.parameter.js]", + "Token from 15 to 16 with scopes [source.js, meta.function.js, meta.function.type.parameter.js, parameter.name.js, variable.parameter.js]", + "Token from 16 to 17 with scopes [source.js, meta.function.js, meta.function.type.parameter.js, meta.brace.round.js]", + "Token from 17 to 18 with scopes [source.js, meta.function.js]", + "Token from 18 to 19 with scopes [source.js, meta.function.js, meta.decl.block.js, meta.brace.curly.js]", + "Token from 19 to 20 with scopes [source.js, meta.function.js, meta.decl.block.js]", + "Token from 20 to 26 with scopes [source.js, meta.function.js, meta.decl.block.js, keyword.control.js]", + "Token from 26 to 28 with scopes [source.js, meta.function.js, meta.decl.block.js]", + "Token from 28 to 29 with scopes [source.js, meta.function.js, meta.decl.block.js, keyword.operator.arithmetic.js]", + "Token from 29 to 32 with scopes [source.js, meta.function.js, meta.decl.block.js]", + "Token from 32 to 33 with scopes [source.js, meta.function.js, meta.decl.block.js, meta.brace.curly.js]" }; + + private static final String[] EXPECTED_MULTI_LINE_TOKENS = { + "Token from 0 to 8 with scopes [source.js, meta.function.js, storage.type.function.js]", + "Token from 8 to 9 with scopes [source.js, meta.function.js]", + "Token from 9 to 12 with scopes [source.js, meta.function.js, entity.name.function.js]", + "Token from 12 to 13 with scopes [source.js, meta.function.js, meta.function.type.parameter.js, meta.brace.round.js]", + "Token from 13 to 14 with scopes [source.js, meta.function.js, meta.function.type.parameter.js, parameter.name.js, variable.parameter.js]", + "Token from 14 to 15 with scopes [source.js, meta.function.js, meta.function.type.parameter.js]", + "Token from 15 to 16 with scopes [source.js, meta.function.js, meta.function.type.parameter.js, parameter.name.js, variable.parameter.js]", + "Token from 16 to 17 with scopes [source.js, meta.function.js, meta.function.type.parameter.js, meta.brace.round.js]", + "Token from 0 to 1 with scopes [source.js, meta.function.js, meta.decl.block.js, meta.brace.curly.js]", + "Token from 1 to 2 with scopes [source.js, meta.function.js, meta.decl.block.js]", + "Token from 2 to 8 with scopes [source.js, meta.function.js, meta.decl.block.js, keyword.control.js]", + "Token from 8 to 10 with scopes [source.js, meta.function.js, meta.decl.block.js]", + "Token from 10 to 11 with scopes [source.js, meta.function.js, meta.decl.block.js, keyword.operator.arithmetic.js]", + "Token from 11 to 14 with scopes [source.js, meta.function.js, meta.decl.block.js]", + "Token from 14 to 15 with scopes [source.js, meta.function.js, meta.decl.block.js, meta.brace.curly.js]" }; + + @Test + public void tokenizeLine() throws Exception { + Registry registry = new Registry(); + String path = "JavaScript.tmLanguage"; + IGrammar grammar = registry.loadGrammarFromPathSync(path, Data.class.getResourceAsStream(path)); + ITokenizeLineResult lineTokens = castNonNull(grammar).tokenizeLine("function add(a,b) { return a+b; }"); + for (int i = 0; i < lineTokens.getTokens().length; i++) { + IToken token = lineTokens.getTokens()[i]; + String s = "Token from " + token.getStartIndex() + " to " + token.getEndIndex() + " with scopes " + + token.getScopes(); + Assertions.assertEquals(EXPECTED_TOKENS[i], s); + } + } + + @Test + public void tokenizeLines() throws Exception { + Registry registry = new Registry(); + String path = "JavaScript.tmLanguage"; + IGrammar grammar = registry.loadGrammarFromPathSync(path, Data.class.getResourceAsStream(path)); + + IStackElement ruleStack = null; + int i = 0; + int j = 0; + String[] lines = { "function add(a,b)", "{ return a+b; }" }; + for (int l = 0; l < lines.length; l++) { + ITokenizeLineResult lineTokens = castNonNull(grammar).tokenizeLine(lines[l], ruleStack); + ruleStack = lineTokens.getRuleStack(); + for (i = 0; i < lineTokens.getTokens().length; i++) { + IToken token = lineTokens.getTokens()[i]; + String s = "Token from " + token.getStartIndex() + " to " + token.getEndIndex() + " with scopes " + + token.getScopes(); + Assertions.assertEquals(EXPECTED_MULTI_LINE_TOKENS[i + j], s); + } + j = i; + } + + } +} diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/GrammarTest2.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/GrammarTest2.java index a69fd5f73..97b0fee52 100644 --- a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/GrammarTest2.java +++ b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/GrammarTest2.java @@ -1,69 +1,90 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.grammar; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.tm4e.core.Data; -import org.eclipse.tm4e.core.registry.Registry; -import org.junit.jupiter.api.Test; - -/** - * Test for grammar tokenizer. - * - */ -class GrammarTest2 { - - @Test - void tokenizeLines() throws Exception { - Registry registry = new Registry(); - String path = "JavaScript.tmLanguage"; - IGrammar grammar = registry.loadGrammarFromPathSync(path, Data.class.getResourceAsStream(path)); - - StackElement ruleStack = null; - int i = 0; - - List lines = new ArrayList<>(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(Data.class.getResourceAsStream("raytracer.ts")));){ - String line = null; - while ((line = reader.readLine()) != null) { - lines.add(line); - } - } catch (Exception e) { - e.printStackTrace(); - } - - int t = 0; - boolean stop = false; - long start = System.currentTimeMillis(); - for (String line : lines) { - ITokenizeLineResult lineTokens = grammar.tokenizeLine(line, ruleStack); - if (stop) { - t = 1000; - Thread.sleep(t); - stop = false; - } - ruleStack = lineTokens.getRuleStack(); - for (i = 0; i < lineTokens.getTokens().length; i++) { - IToken token = lineTokens.getTokens()[i]; - String s = "Token from " + token.getStartIndex() + " to " + token.getEndIndex() + " with scopes " - + token.getScopes(); - System.err.println(s); - // Assert.assertEquals(EXPECTED_MULTI_LINE_TOKENS[i + j], s); - } - } - System.out.println(System.currentTimeMillis() - start - t); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.grammar; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; +import static org.junit.jupiter.api.Assertions.*; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; + +import org.eclipse.tm4e.core.Data; +import org.eclipse.tm4e.core.registry.Registry; +import org.junit.jupiter.api.Test; + +/** + * Test for grammar tokenizer. + * + */ +class GrammarTest2 { + + @Test + void tokenizeLines() throws Exception { + final var registry = new Registry(); + final var path = "JavaScript.tmLanguage"; + try (var is = Data.class.getResourceAsStream(path)) { + final var grammar = castNonNull(registry.loadGrammarFromPathSync(path, is)); + + IStackElement ruleStack = null; + int i = 0; + + final var lines = new ArrayList(); + try (var reader = new BufferedReader( + new InputStreamReader(Data.class.getResourceAsStream("raytracer.ts")));) { + String line = null; + while ((line = reader.readLine()) != null) { + lines.add(line); + } + } + + int t = 0; + boolean stop = false; + long start = System.currentTimeMillis(); + for (String line : lines) { + ITokenizeLineResult lineTokens = grammar.tokenizeLine(line, ruleStack); + if (stop) { + t = 1000; + Thread.sleep(t); + stop = false; + } + ruleStack = lineTokens.getRuleStack(); + for (i = 0; i < lineTokens.getTokens().length; i++) { + IToken token = lineTokens.getTokens()[i]; + String s = "Token from " + token.getStartIndex() + " to " + token.getEndIndex() + " with scopes " + + token.getScopes(); + // System.err.println(s); + // Assert.assertEquals(EXPECTED_MULTI_LINE_TOKENS[i + j], s); + } + } + System.out.println(System.currentTimeMillis() - start - t); + } + } + + @Test + public void testYamlMultiline() throws Exception { + final var registry = new Registry(); + final var path = "yaml.tmLanguage.json"; + try (var in = Data.class.getResourceAsStream(path)) { + final var grammar = castNonNull(registry.loadGrammarFromPathSync(path, in)); + String lines = ">\n should.be.string.unquoted.block.yaml\n should.also.be.string.unquoted.block.yaml"; + final var result = TokenizationUtils.tokenizeText(lines, grammar).iterator(); + assertTrue(Arrays.stream(result.next().getTokens()) + .anyMatch(t -> t.getScopes().contains("keyword.control.flow.block-scalar.folded.yaml"))); + assertTrue(Arrays.stream(result.next().getTokens()) + .anyMatch(t -> t.getScopes().contains("string.unquoted.block.yaml"))); + assertTrue(Arrays.stream(result.next().getTokens()) + .anyMatch(t -> t.getScopes().contains("string.unquoted.block.yaml"))); + } + } +} diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/MarkDown.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/MarkDown.java index bc413b064..51dcabc2d 100644 --- a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/MarkDown.java +++ b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/MarkDown.java @@ -1,69 +1,65 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.grammar; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.tm4e.core.Data; -import org.eclipse.tm4e.core.registry.Registry; - -public class MarkDown { - - public static void main(String[] args) throws Exception { - Registry registry = new Registry(); - String path = "Markdown.tmLanguage"; - IGrammar grammar = registry.loadGrammarFromPathSync(path, Data.class.getResourceAsStream(path)); - - List lines = new ArrayList<>(); - BufferedReader reader = null; - try { - reader = new BufferedReader(new InputStreamReader(Data.class.getResourceAsStream("test.md.txt"))); - String line = null; - while ((line = reader.readLine()) != null) { - lines.add(line); - } - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (reader != null) { - reader.close(); - } - } - - - long start = System.currentTimeMillis(); - - StackElement ruleStack = null; - int i = 0; - for (String line : lines) { - ITokenizeLineResult lineTokens = grammar.tokenizeLine(line, ruleStack); - ruleStack = lineTokens.getRuleStack(); - for (i = 0; i < lineTokens.getTokens().length; i++) { -// IToken token = lineTokens.getTokens()[i]; -// String s = "Token from " + token.getStartIndex() + " to " + token.getEndIndex() + " with scopes " -// + token.getScopes(); - //System.err.println(s); - // Assert.assertEquals(EXPECTED_MULTI_LINE_TOKENS[i + j], s); - } - } - System.err.println(System.currentTimeMillis() - start); - } - - static String convertStreamToString(java.io.InputStream is) { - try (java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A")) { - return s.hasNext() ? s.next() : ""; - } - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.grammar; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.tm4e.core.Data; +import org.eclipse.tm4e.core.registry.Registry; + +public class MarkDown { + + public static void main(String[] args) throws Exception { + Registry registry = new Registry(); + String path = "Markdown.tmLanguage"; + IGrammar grammar = castNonNull(registry.loadGrammarFromPathSync(path, Data.class.getResourceAsStream(path))); + + List lines = new ArrayList<>(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(Data.class.getResourceAsStream("test.md.txt")))) { + String line = null; + while ((line = reader.readLine()) != null) { + lines.add(line); + } + } catch (Exception e) { + e.printStackTrace(); + } + + + long start = System.currentTimeMillis(); + + IStackElement ruleStack = null; + int i = 0; + for (String line : lines) { + ITokenizeLineResult lineTokens = grammar.tokenizeLine(line, ruleStack); + ruleStack = lineTokens.getRuleStack(); + for (i = 0; i < lineTokens.getTokens().length; i++) { +// IToken token = lineTokens.getTokens()[i]; +// String s = "Token from " + token.getStartIndex() + " to " + token.getEndIndex() + " with scopes " +// + token.getScopes(); + //System.err.println(s); + // Assert.assertEquals(EXPECTED_MULTI_LINE_TOKENS[i + j], s); + } + } + System.err.println(System.currentTimeMillis() - start); + } + + static String convertStreamToString(java.io.InputStream is) { + try (java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A")) { + return s.hasNext() ? s.next() : ""; + } + } +} diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/TokenizationUtils.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/TokenizationUtils.java new file mode 100644 index 000000000..66991e7e5 --- /dev/null +++ b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/TokenizationUtils.java @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2022 Sebastian Thomschke and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Sebastian Thomschke - initial implementation + */ +package org.eclipse.tm4e.core.grammar; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.function.Function; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.Nullable; + +import com.google.common.base.Splitter; + +public class TokenizationUtils { + + private static final Splitter BY_LINE_SPLITTER = Splitter.onPattern("\\r?\\n"); + + /** + * Lazy tokenizes the given text. + * + * @param text the text to tokenize + * + * @return The stream of {@link ITokenizeLineResult}, each item covering 1 line of the text + */ + public static Stream tokenizeText(final CharSequence text, IGrammar grammar) { + if (text.length() == 0) { + return Stream.empty(); + } + + return BY_LINE_SPLITTER.splitToStream(text).map(new Function() { + @Nullable + IStackElement prevStack; + + @Override + public ITokenizeLineResult apply(String line) { + final var tokenized = grammar.tokenizeLine(line, prevStack); + prevStack = tokenized.getRuleStack(); + return tokenized; + } + }); + } + + /** + * Lazy tokenizes the text provided by the given input stream. + * + * @param text the text to tokenize + * + * @return The stream of {@link ITokenizeLineResult}, each item covering 1 line of the text + * + * @throws IOException + */ + public static Stream tokenizeText(final InputStream text, IGrammar grammar) + throws IOException { + var reader = new BufferedReader(new InputStreamReader(text)); + return reader.lines().map(new Function() { + @Nullable + IStackElement prevStack; + + @Override + public ITokenizeLineResult apply(String line) { + final var tokenized = grammar.tokenizeLine(line, prevStack); + prevStack = tokenized.getRuleStack(); + return tokenized; + } + }); + } + + private TokenizationUtils() { + } +} diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/grammar/StackElementMetadataTest.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/grammar/StackElementMetadataTest.java new file mode 100644 index 000000000..ccdfc7af0 --- /dev/null +++ b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/grammar/StackElementMetadataTest.java @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.grammar; + +import static org.eclipse.tm4e.core.internal.theme.FontStyle.*; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * {@link StackElementMetadata} tests same than vscode-textmate. + * + * @see + * github.com/Microsoft/vscode-textmate/blob/master/src/tests/grammar.test.ts + */ +public class StackElementMetadataTest { + + @Test + public void testWorks() { + int value = StackElementMetadata.set(0, 1, OptionalStandardTokenType.RegEx, null, Underline | Bold, 101, 102); + assertEquals(value, 1, StandardTokenType.RegEx, false, Underline | Bold, 101, 102); + } + + @Test + public void testCanOverwriteLanguageId() { + int value = StackElementMetadata.set(0, 1, OptionalStandardTokenType.RegEx, null, Underline | Bold, 101, 102); + assertEquals(value, 1, StandardTokenType.RegEx, false, Underline | Bold, 101, 102); + + value = StackElementMetadata.set(value, 2, OptionalStandardTokenType.NotSet, null, NotSet, 0, 0); + assertEquals(value, 2, StandardTokenType.RegEx, false, Underline | Bold, 101, 102); + } + + @Test + public void testCanOverwriteTokenType() { + int value = StackElementMetadata.set(0, 1, OptionalStandardTokenType.RegEx, null, Underline | Bold, 101, 102); + assertEquals(value, 1, StandardTokenType.RegEx, false, Underline | Bold, 101, 102); + + value = StackElementMetadata.set(value, 0, OptionalStandardTokenType.Comment, null, NotSet, 0, 0); + assertEquals(value, 1, StandardTokenType.Comment, false, Underline | Bold, 101, 102); + } + + @Test + public void testCanOverwriteFontStyle() { + int value = StackElementMetadata.set(0, 1, OptionalStandardTokenType.RegEx, null, Underline | Bold, 101, 102); + assertEquals(value, 1, StandardTokenType.RegEx, false, Underline | Bold, 101, 102); + + value = StackElementMetadata.set(value, 0, OptionalStandardTokenType.NotSet, null, None, 0, 0); + assertEquals(value, 1, StandardTokenType.RegEx, false, None, 101, 102); + } + + @Test + public void testCanOverwriteFontStyleWithStrikethrough() { + int value = StackElementMetadata.set(0, 1, OptionalStandardTokenType.RegEx, null, Strikethrough, 101, 102); + assertEquals(value, 1, StandardTokenType.RegEx, false, Strikethrough, 101, 102); + + value = StackElementMetadata.set(value, 0, OptionalStandardTokenType.NotSet, null, None, 0, 0); + assertEquals(value, 1, StandardTokenType.RegEx, false, None, 101, 102); + } + + @Test + public void testCanOverwriteForeground() { + int value = StackElementMetadata.set(0, 1, OptionalStandardTokenType.RegEx, null, Underline | Bold, 101, 102); + assertEquals(value, 1, StandardTokenType.RegEx, false, Underline | Bold, 101, 102); + + value = StackElementMetadata.set(value, 0, OptionalStandardTokenType.NotSet, null, NotSet, 5, 0); + assertEquals(value, 1, StandardTokenType.RegEx, false, Underline | Bold, 5, 102); + } + + @Test + public void testCanOverwriteBackground() { + int value = StackElementMetadata.set(0, 1, OptionalStandardTokenType.RegEx, null, Underline | Bold, 101, 102); + assertEquals(value, 1, StandardTokenType.RegEx, false, Underline | Bold, 101, 102); + + value = StackElementMetadata.set(value, 0, OptionalStandardTokenType.NotSet, null, NotSet, 0, 7); + assertEquals(value, 1, StandardTokenType.RegEx, false, Underline | Bold, 101, 7); + } + + @Test + public void testCanWorkAtMaxValues() { + int maxLangId = 255; + int maxTokenType = StandardTokenType.Comment | StandardTokenType.Other | StandardTokenType.RegEx + | StandardTokenType.String; + int maxFontStyle = Bold | Italic | Underline; + int maxForeground = 511; + int maxBackground = 254; + + int value = StackElementMetadata.set(0, maxLangId, maxTokenType, true, maxFontStyle, maxForeground, + maxBackground); + assertEquals(value, maxLangId, maxTokenType, true, maxFontStyle, maxForeground, maxBackground); + } + + private static void assertEquals(int metadata, int languageId, int /*StandardTokenType*/ tokenType, + boolean containsBalancedBrackets, int /*FontStyle*/ fontStyle, int foreground, int background) { + String actual = "{\n" + + "languageId: " + StackElementMetadata.getLanguageId(metadata) + ",\n" + + "tokenType: " + StackElementMetadata.getTokenType(metadata) + ",\n" + + "containsBalancedBrackets: " + StackElementMetadata.containsBalancedBrackets(metadata) + ",\n" + + "fontStyle: " + StackElementMetadata.getFontStyle(metadata) + ",\n" + + "foreground: " + StackElementMetadata.getForeground(metadata) + ",\n" + + "background: " + StackElementMetadata.getBackground(metadata) + ",\n" + + "}"; + + String expected = "{\n" + + "languageId: " + languageId + ",\n" + + "tokenType: " + tokenType + ",\n" + + "containsBalancedBrackets: " + containsBalancedBrackets + ",\n" + + "fontStyle: " + fontStyle + ",\n" + + "foreground: " + foreground + ",\n" + + "background: " + background + ",\n" + + "}"; + + Assertions.assertEquals(expected, actual, "equals for " + StackElementMetadata.toBinaryStr(metadata)); + } +} diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/grammar/parser/json/JSONPListParserTest.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/grammar/parser/json/JSONPListParserTest.java deleted file mode 100644 index ef5ee3ded..000000000 --- a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/grammar/parser/json/JSONPListParserTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.grammar.parser.json; - -import org.eclipse.tm4e.core.internal.grammar.reader.GrammarReader; -import org.eclipse.tm4e.core.internal.grammar.reader.IGrammarParser; -import org.eclipse.tm4e.core.internal.types.IRawGrammar; -import org.junit.jupiter.api.Test; - -public class JSONPListParserTest { - - @Test - public void testCsharp() throws Exception { - IGrammarParser parser = GrammarReader.JSON_PARSER; - IRawGrammar grammar = parser.parse(JSONPListParserTest.class.getResourceAsStream("csharp.json")); - System.err.println(grammar); - } -} diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/grammar/parser/xml/XMLPlistParserTest.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/grammar/parser/xml/XMLPlistParserTest.java deleted file mode 100644 index ea39eeae2..000000000 --- a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/grammar/parser/xml/XMLPlistParserTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.internal.grammar.parser.xml; - -import org.eclipse.tm4e.core.internal.grammar.reader.GrammarReader; -import org.eclipse.tm4e.core.internal.grammar.reader.IGrammarParser; -import org.eclipse.tm4e.core.internal.types.IRawGrammar; -import org.junit.jupiter.api.Test; - -public class XMLPlistParserTest { - - @Test - public void testCsharp() throws Exception { - IGrammarParser parser = GrammarReader.XML_PARSER; - IRawGrammar grammar = parser.parse(XMLPlistParserTest.class.getResourceAsStream("JavaScript.tmLanguage")); - System.err.println(grammar); - } -} diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/grammar/reader/GrammarReaderTest.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/grammar/reader/GrammarReaderTest.java new file mode 100644 index 000000000..a461cc2aa --- /dev/null +++ b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/grammar/reader/GrammarReaderTest.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2022 Sebastian Thomschke and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Sebastian Thomschke - initial implementation + */ +package org.eclipse.tm4e.core.internal.grammar.reader; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.InputStream; + +import org.eclipse.tm4e.core.Data; +import org.eclipse.tm4e.core.internal.types.IRawGrammar; +import org.junit.jupiter.api.Test; + +public class GrammarReaderTest { + + private IRawGrammar loadGrammar(String path) throws Exception { + try (InputStream is = Data.class.getResourceAsStream(path)) { + return GrammarReader.readGrammarSync(path, is); + } + } + + /** + * Loads the same TextMate grammar in different formats and checks + * loading them results in equal IRawGrammar objects. + */ + @Test + public void testLoadDifferentPlistFormats() throws Exception { + IRawGrammar grammarFromXML = loadGrammar("JavaScript.tmLanguage"); + IRawGrammar grammarFromJSON = loadGrammar("JavaScript.tmLanguage.json"); + IRawGrammar grammarFromYAML = loadGrammar("JavaScript.tmLanguage.yaml"); + + assertNotNull(grammarFromXML); + assertFalse(grammarFromXML.getFileTypes().isEmpty()); + + assertEquals(grammarFromXML, grammarFromJSON); + assertEquals(grammarFromJSON, grammarFromYAML); + } +} diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/oniguruma/OnigScannerTest.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/oniguruma/OnigScannerTest.java new file mode 100644 index 000000000..21e411ffc --- /dev/null +++ b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/oniguruma/OnigScannerTest.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.oniguruma; + +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +class OnigScannerTest { + + @Test + void testOnigScanner() { + OnigScanner scanner = new OnigScanner(Arrays.asList("c", "a(b)?")); + OnigNextMatchResult result = scanner.findNextMatchSync("abc", 0); + assertNotNull(result); + assertEquals(1, result.getIndex()); + assertArrayEquals(new OnigCaptureIndex[] { + new OnigCaptureIndex(0, 0, 2), + new OnigCaptureIndex(1, 1, 2) }, + result.getCaptureIndices()); + + scanner = new OnigScanner(Arrays.asList("a([b-d])c")); + result = scanner.findNextMatchSync("!abcdef", 0); + assertNotNull(result); + assertEquals(0, result.getIndex()); + assertArrayEquals(new OnigCaptureIndex[] { + new OnigCaptureIndex(0, 1, 4), + new OnigCaptureIndex(1, 2, 3) }, + result.getCaptureIndices()); + + } +} diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/oniguruma/OnigStringTest.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/oniguruma/OnigStringTest.java new file mode 100644 index 000000000..25495a42a --- /dev/null +++ b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/oniguruma/OnigStringTest.java @@ -0,0 +1,134 @@ +package org.eclipse.tm4e.core.internal.oniguruma; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +class OnigStringTest { + + private OnigString verifyBasics(final String string, final Class expectedType) { + final OnigString onigString = OnigString.of(string); + assertInstanceOf(expectedType, onigString); + assertEquals(string, onigString.string); + assertTrue(onigString.toString().contains(string)); + + assertEquals(onigString.bytesCount, onigString.bytesUTF8.length); + + /* + * getByteIndexOfChar tests + */ + assertThrows(ArrayIndexOutOfBoundsException.class, () -> onigString.getByteIndexOfChar(-1)); + assertEquals(0, onigString.getByteIndexOfChar(0)); + if (!string.isEmpty()) + onigString.getByteIndexOfChar(string.length() - 1); // does not throws exception, because in range + onigString.getByteIndexOfChar(string.length()); // does not throws exception, because of internal workaround + assertThrows(ArrayIndexOutOfBoundsException.class, () -> onigString.getByteIndexOfChar(string.length() + 1)); + + /* + * getCharIndexOfByte tests + */ + assertThrows(ArrayIndexOutOfBoundsException.class, () -> onigString.getCharIndexOfByte(-1)); + assertEquals(0, onigString.getCharIndexOfByte(0)); + if (!string.isEmpty()) { + // does not throws exception, because in range + assertEquals(string.length() - 1, onigString.getCharIndexOfByte(onigString.bytesCount - 1)); + } + // does not throws exception, because of internal workaround + assertEquals(string.length(), onigString.getCharIndexOfByte(onigString.bytesCount)); + + assertThrows(ArrayIndexOutOfBoundsException.class, + () -> onigString.getCharIndexOfByte(onigString.bytesCount + 1)); + + return onigString; + } + + @Test + void testEmptyStrings() { + String string = ""; + OnigString onigString = verifyBasics(string, OnigString.SingleByteString.class); + + assertEquals(0, onigString.bytesCount); + } + + @Test + void testSingleBytesStrings() { + String string = "ab"; + OnigString onigString = verifyBasics(string, OnigString.SingleByteString.class); + + assertEquals(2, onigString.bytesCount); + + /* + * getByteIndexOfChar tests + */ + assertEquals(1, onigString.getByteIndexOfChar(1)); + assertEquals(string.length() - 1, onigString.getByteIndexOfChar(string.length() - 1)); + + /* + * getCharIndexOfByte tests + */ + assertEquals(1, onigString.getCharIndexOfByte(1)); // b + assertEquals(2, onigString.getCharIndexOfByte(2)); // does not throws exception, because of internal workaround + assertThrows(ArrayIndexOutOfBoundsException.class, () -> onigString.getCharIndexOfByte(3)); + } + + @Test + void testMultiByteString() { + String string = "áé"; + OnigString onigString = verifyBasics(string, OnigString.MultiByteString.class); + + assertEquals(4, onigString.bytesCount); + + /* + * getByteIndexOfChar tests + */ + assertEquals(2, onigString.getByteIndexOfChar(1)); + + /* + * getCharIndexOfByte tests + */ + assertEquals(0, onigString.getCharIndexOfByte(1)); // á + assertEquals(1, onigString.getCharIndexOfByte(2)); // é + assertEquals(1, onigString.getCharIndexOfByte(3)); // é + assertEquals(2, onigString.getCharIndexOfByte(4)); // this is an internal workaround + assertThrows(ArrayIndexOutOfBoundsException.class, () -> onigString.getCharIndexOfByte(5)); + + } + + @Test + void testMixedMultiByteString() { + String string = "myááçóúôõaab"; + OnigString onigString = verifyBasics(string, OnigString.MultiByteString.class); + + assertEquals(19, onigString.bytesCount); + + /* + * getByteIndexOfChar tests + */ + assertEquals(1, onigString.getByteIndexOfChar(1)); + assertEquals(2, onigString.getByteIndexOfChar(2)); + assertEquals(4, onigString.getByteIndexOfChar(3)); + assertEquals(6, onigString.getByteIndexOfChar(4)); + assertEquals(8, onigString.getByteIndexOfChar(5)); + assertEquals(10, onigString.getByteIndexOfChar(6)); + assertEquals(12, onigString.getByteIndexOfChar(7)); + + /* + * getCharIndexOfByte tests + */ + assertEquals(1, onigString.getCharIndexOfByte(1)); + assertEquals(2, onigString.getCharIndexOfByte(2)); + assertEquals(2, onigString.getCharIndexOfByte(3)); + assertEquals(3, onigString.getCharIndexOfByte(4)); + assertEquals(3, onigString.getCharIndexOfByte(5)); + assertEquals(4, onigString.getCharIndexOfByte(6)); + assertEquals(4, onigString.getCharIndexOfByte(7)); + assertEquals(5, onigString.getCharIndexOfByte(8)); + assertEquals(6, onigString.getCharIndexOfByte(10)); + assertEquals(7, onigString.getCharIndexOfByte(12)); + assertEquals(10, onigString.getCharIndexOfByte(17)); // a + assertEquals(11, onigString.getCharIndexOfByte(18)); // b + + assertEquals(12, onigString.getCharIndexOfByte(19)); // this is an internal workaround + assertThrows(ArrayIndexOutOfBoundsException.class, () -> onigString.getCharIndexOfByte(20)); + } +} diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/parser/PListParserTest.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/parser/PListParserTest.java new file mode 100644 index 000000000..6e337d782 --- /dev/null +++ b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/internal/parser/PListParserTest.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.internal.parser; + +import static org.junit.jupiter.api.Assertions.*; + +import org.eclipse.tm4e.core.Data; +import org.eclipse.tm4e.core.internal.grammar.RawGrammar; +import org.eclipse.tm4e.core.internal.grammar.reader.GrammarReader; +import org.junit.jupiter.api.Test; + +public class PListParserTest { + + @Test + void testParseJSONPList() throws Exception { + final PListParser parser = new PListParserJSON<>(GrammarReader.OBJECT_FACTORY); + try (final var is = Data.class.getResourceAsStream("csharp.json")) { + final var grammar = parser.parse(is); + assertNotNull(grammar); + assertFalse(grammar.getFileTypes().isEmpty()); + System.out.println(grammar); + } + } + + @Test + void testParseYAMLPlist() throws Exception { + final PListParser parser = new PListParserYAML<>(GrammarReader.OBJECT_FACTORY); + try (final var is = Data.class.getResourceAsStream("JavaScript.tmLanguage.yaml")) { + final var grammar = parser.parse(is); + assertNotNull(grammar); + assertFalse(grammar.getFileTypes().isEmpty()); + System.out.println(grammar); + } + } + + @Test + void testParseXMLPlist() throws Exception { + final PListParser parser = new PListParserXML<>(GrammarReader.OBJECT_FACTORY); + try (final var is = Data.class.getResourceAsStream("JavaScript.tmLanguage")) { + final var grammar = parser.parse(is); + assertNotNull(grammar); + assertFalse(grammar.getFileTypes().isEmpty()); + System.out.println(grammar); + } + } +} diff --git a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/css/CSSParserTest.java b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/theme/css/CSSParserTest.java similarity index 87% rename from org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/css/CSSParserTest.java rename to org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/theme/css/CSSParserTest.java index ea47b0513..12aef9d24 100644 --- a/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/css/CSSParserTest.java +++ b/org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/theme/css/CSSParserTest.java @@ -1,29 +1,28 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.core.css; - -import org.eclipse.tm4e.core.theme.IStyle; -import org.eclipse.tm4e.core.theme.css.CSSParser; - -public class CSSParserTest { - - public static void main(String[] args) throws Exception { - CSSParser parser = new CSSParser(".comment {color:rgb(0,1,2)} .comment.ts {color:rgb(0,1,2)}"); - String[] names = "comment".split("[.]"); - parser.getBestStyle(names); - - names = "comment.ts".split("[.]"); - IStyle style = parser.getBestStyle(names); - - System.err.println(style.getColor().red); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.core.theme.css; + +import org.eclipse.tm4e.core.theme.IStyle; + +public class CSSParserTest { + + public static void main(String[] args) throws Exception { + CSSParser parser = new CSSParser(".comment {color:rgb(0,1,2)} .comment.ts {color:rgb(0,1,2)}"); + String[] names = "comment".split("[.]"); + parser.getBestStyle(names); + + names = "comment.ts".split("[.]"); + IStyle style = parser.getBestStyle(names); + + System.err.println(style.getColor().red); + } +} diff --git a/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/Angular2TypeScript.tmLanguage b/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/Angular2TypeScript.tmLanguage index 4befb89a2..ecfdca5ab 100644 --- a/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/Angular2TypeScript.tmLanguage +++ b/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/Angular2TypeScript.tmLanguage @@ -1,2003 +1,2003 @@ - - - - - fileTypes - - ts - - name - TypeScript - patterns - - - include - #expression - - - repository - - access-modifier - - match - \b(public|protected|private)\b - name - storage.modifier.ts - - arithmetic-operator - - match - \*|/|\-\-|\-|\+\+|\+|% - name - keyword.operator.arithmetic.ts - - array-literal - - begin - \[ - beginCaptures - - 0 - - name - meta.brace.square.ts - - - end - \] - endCaptures - - 0 - - name - meta.brace.square.ts - - - name - meta.array.literal.ts - patterns - - - include - #expression - - - - assignment-operator - - match - <<=|>>=|>>>=|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^= - name - keyword.operator.assignment.ts - - block - - begin - \{ - beginCaptures - - 0 - - name - meta.brace.curly.ts - - - end - \} - endCaptures - - 0 - - name - meta.brace.curly.ts - - - name - meta.block.ts - patterns - - - include - #expression - - - include - #object-member - - - - boolean-literal - - match - \b(false|true)\b - name - constant.language.boolean.ts - - cast - - begin - (?:(?<=return|throw|yield|[=(,:>]))\s*(<)(?!<?\=) - beginCaptures - - 1 - - name - meta.brace.angle.ts - - - end - > - endCaptures - - 0 - - name - meta.brace.angle.ts - - - name - cast.expr.ts - patterns - - - include - #type - - - - comment - - name - comment.ts - patterns - - - include - #comment-block-doc - - - include - #comment-block - - - include - #comment-line - - - - comment-block - - begin - /\* - end - \*/ - name - comment.block.ts - - comment-block-doc - - begin - /\*\*(?!/) - end - \*/ - name - comment.block.documentation.ts - - comment-line - - match - (//).*$\n? - name - comment.line.ts - - control-statement - - match - (?<!\.)\b(break|catch|continue|debugger|declare|do|else|finally|for|if|return|switch|throw|try|while|with|super|case|default)\b - name - keyword.control.ts - - decl-block - - begin - \{ - beginCaptures - - 0 - - name - meta.brace.curly.ts - - - end - \} - endCaptures - - 0 - - name - meta.brace.curly.ts - - - name - meta.decl.block.ts - patterns - - - include - #expression - - - - declaration - - name - meta.declaration.ts - patterns - - - include - #function-declaration - - - include - #object-declaration - - - include - #type-declaration - - - include - #enum-declaration - - - - enum-declaration - - captures - - 1 - - name - storage.modifier.ts - - 2 - - name - storage.type.ts - - 3 - - name - entity.name.class.ts - - - match - (?:\b(const)\s+)?\b(enum)\s+([a-zA-Z_$][\w$]*) - name - meta.enum.declaration.ts - - expression - - name - meta.expression.ts - patterns - - - include - #ngTemplate - - - include - #for-in-simple - - - include - #string - - - include - #regex - - - include - #template - - - include - #comment - - - include - #literal - - - include - #paren-expression - - - include - #var-expr - - - include - #declaration - - - include - #cast - - - include - #new-expr - - - include - #block - - - include - #expression-operator - - - include - #relational-operator - - - include - #arithmetic-operator - - - include - #logic-operator - - - include - #assignment-operator - - - include - #storage-keyword - - - include - #function-call - - - include - #switch-case - - - include - #control-statement - - - - expression-operator - - match - =>|\b(delete|export|import|in|instanceof|module|namespace|new|typeof|void)\b - name - keyword.operator.ts - - field-declaration - - begin - (?<!\()\s*\b([a-zA-Z_$][\w$]*)\s*(\?\s*)?(?=(=|:)) - beginCaptures - - 1 - - name - variable.ts - - 2 - - name - keyword.operator.ts - - - end - (?=\}|;|,)|(?<=\}) - name - meta.field.declaration.ts - patterns - - - include - #expression - - - - for-in-simple - - captures - - 1 - - name - storage.type.ts - - 3 - - name - keyword.operator.ts - - - match - (?<=\()\s*\b(var|let|const)\s+([a-zA-Z_$][\w$]*)\s+(in|of)\b - name - forin.expr.ts - - function-call - - name - functioncall.expr.ts - patterns - - - include - #type-parameters - - - include - #paren-expression - - - - function-declaration - - begin - \b(?:(export)\s+)?(function\b)(?:\s+([a-zA-Z_$][\w$]*))?\s* - beginCaptures - - 1 - - name - storage.modifier.ts - - 2 - - name - storage.type.function.ts - - 3 - - name - entity.name.function.ts - - - end - (?=;|\})|(?<=\}) - name - meta.function.ts - patterns - - - include - #comment - - - include - #type-parameters - - - include - #function-type-parameters - - - include - #return-type - - - include - #function-overload-declaration - - - include - #decl-block - - - - function-overload-declaration - - captures - - 1 - - name - storage.modifier.ts - - 2 - - name - storage.type.function.ts - - 3 - - name - entity.name.function.ts - - - match - \b(?:(export)\s+)?(function\b)(?:\s+([a-zA-Z_$][\w$]*))?\s* - name - meta.function.overload.ts - - function-type-parameters - - begin - \( - beginCaptures - - 0 - - name - meta.brace.round.ts - - - end - \) - endCaptures - - 0 - - name - meta.brace.round.ts - - - name - meta.function.type.parameter.ts - patterns - - - include - #comment - - - include - #parameter-name - - - include - #type-annotation - - - include - #variable-initializer - - - - htmlComment - - begin - <!-- - end - --> - name - comment.block.ts - - htmlText - - match - .*?(?=({{)|(\$\{)|<|$) - name - string.ts - - indexer-declaration - - begin - \[ - beginCaptures - - 0 - - name - meta.brace.square.ts - - - end - (\])\s*(\?\s*)?|$ - endCaptures - - 1 - - name - meta.brace.square.ts - - 2 - - name - keyword.operator.ts - - - name - meta.indexer.declaration.ts - patterns - - - include - #type-annotation - - - include - #indexer-parameter - - - include - #expression - - - - indexer-parameter - - captures - - 1 - - name - variable.parameter.ts - - - match - ([a-zA-Z_$][\w$]*)(?=\:) - name - meta.indexer.parameter.ts - - literal - - name - literal.ts - patterns - - - include - #numeric-literal - - - include - #boolean-literal - - - include - #null-literal - - - include - #undefined-literal - - - include - #array-literal - - - include - #this-literal - - - - logic-operator - - match - \!|&|~|\||&&|\|\| - name - keyword.operator.arithmetic.ts - - method-declaration - - begin - \b(?:(abstract)\s+)?\b(?:(public|private|protected)\s+)?(?:(get|set)\s+)?(?:(new)|(?:([a-zA-Z_$][\.\w$]*)\s*(\??)))?\s*(?=\(|\<) - beginCaptures - - 1 - - name - storage.modifier.ts - - 2 - - name - storage.modifier.ts - - 3 - - name - storage.type.property.ts - - 4 - - name - keyword.operator.ts - - 5 - - name - entity.name.function.ts - - 6 - - name - keyword.operator.ts - - - end - (?=\}|;|,)|(?<=\}) - name - meta.method.declaration.ts - patterns - - - include - #comment - - - include - #type-parameters - - - include - #function-type-parameters - - - include - #type-annotation - - - include - #method-overload-declaration - - - include - #decl-block - - - - method-overload-declaration - - captures - - 1 - - name - storage.modifier.ts - - 2 - - name - keyword.operator.ts - - 3 - - name - entity.name.function.ts - - 4 - - name - keyword.operator.ts - - - match - \b(?:(public|private|protected)\s+)?(?:(new)|(?:([a-zA-Z_$][\.\w$]*)\s*(\??)))?\s*(?=\(|\<) - name - meta.method.overload.declaration.ts - - new-expr - - begin - \b(new)\b - beginCaptures - - 1 - - name - keyword.operator.ts - - - end - (?=[(;]|$) - name - new.expr.ts - patterns - - - include - #type - - - include - #comment - - - - ngAttrib - - begin - ([a-zA-Z\$][a-zA-Z0-9\$\-]*) - beginCaptures - - 1 - - name - entity.name.class.ts - - - end - (?=[^'=]) - name - meta.attribute.ts - patterns - - - include - #ngAttribValue - - - - ngAttribValue - - begin - = - beginCaptures - - 0 - - name - punctuation.separator.key-value.ts - - - end - (?<=') - name - meta.attribute.ts - patterns - - - include - #qstring-single - - - - ngBinding - - begin - (?:\(|\[|(?:\[\())([a-zA-Z\$][a-zA-Z0-9\$\-]*)(?:(?:\)\])|\)|\]) - beginCaptures - - 1 - - name - keyword.control.ts - - - end - (?=[^'=]) - name - meta.binding-name.ts - patterns - - - include - #ngAttribValue - - - - ngDirective - - begin - \*([a-zA-Z\$][a-zA-Z0-9\$\-]*) - beginCaptures - - 1 - - name - keyword.control.ts - - - end - (?=[^'=]) - name - meta.directive-name.ts - patterns - - - include - #ngAttribValue - - - - ngExpr - - begin - {{ - beginCaptures - - 0 - - name - keyword.operator.ts - - - end - }} - endCaptures - - 0 - - name - keyword.operator.ts - - - name - meta.expression.ts - patterns - - - include - #expression - - - - ngTag - - begin - (<)([a-zA-Z\$][a-zA-Z0-9\$\-]*) - beginCaptures - - 1 - - name - keyword.operator.ts - - 2 - - name - entity.name.tag.ts - - - end - (/>)|(?:(</)([a-zA-Z\$][a-zA-Z0-9\$\-]*)(>)) - endCaptures - - 1 - - name - keyword.operator.ts - - 2 - - name - keyword.operator.ts - - 3 - - name - entity.name.tag.ts - - 4 - - name - keyword.operator.ts - - - name - meta.tag.ts - patterns - - - include - #ngAttrib - - - include - #ngDirective - - - include - #ngBinding - - - include - #ngTagEnd - - - - ngTagEnd - - begin - > - beginCaptures - - 0 - - name - keyword.operator.ts - - - end - (?=</) - name - meta.tagend.ts - patterns - - - include - #ngml - - - - ngTemplate - - begin - (?:(?<=^|\stemplate:)|(?<=/\*\* @html \*/))\s*(`) - beginCaptures - - 1 - - name - string.template.ts - - - end - ` - endCaptures - - 0 - - name - string.template.ts - - - name - meta.ngTemplate.ts - patterns - - - include - #ngml - - - - ngml - - name - meta.ngml.ts - patterns - - - include - #ngTag - - - include - #ngExpr - - - include - #htmlComment - - - include - #template-substitution-element - - - include - #htmlText - - - - null-literal - - match - \b(null)\b - name - constant.language.null.ts - - numeric-literal - - match - \b(?<=[^$])((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?))\b - name - constant.numeric.ts - - object-body - - begin - \{ - beginCaptures - - 0 - - name - meta.brace.curly.ts - - - end - \} - endCaptures - - 0 - - name - meta.brace.curly.ts - - - name - meta.object.body.ts - patterns - - - include - #string - - - include - #comment - - - include - #field-declaration - - - include - #method-declaration - - - include - #indexer-declaration - - - include - #type-annotation - - - include - #variable-initializer - - - include - #access-modifier - - - include - #static-modifier - - - include - #property-accessor - - - - object-declaration - - begin - \b(?:(export)\s+)?\b(?:(abstract)\s+)?\b(?<!\.)(class|interface)\b - beginCaptures - - 1 - - name - storage.modifier.ts - - 2 - - name - storage.modifier.ts - - 3 - - name - storage.type.ts - - - end - (?<=\}) - endCaptures - - 1 - - name - brace.curly.ts - - - name - meta.declaration.object.ts - patterns - - - include - #comment - - - include - #object-heritage - - - include - #object-name - - - include - #type-parameters - - - include - #object-body - - - - object-heritage - - begin - (?:\b(extends|implements)) - beginCaptures - - 1 - - name - keyword.other.ts - - - end - (?=\{) - endCaptures - - 1 - - name - brace.curly.ts - - - name - meta.object.heritage.ts - patterns - - - include - #comment - - - include - #type-parameters - - - include - #object-heritage-parent - - - - object-heritage-parent - - captures - - 1 - - name - storage.type.ts - - - match - (?:\s*([a-zA-Z_$][\w$]*)) - name - meta.object.heritage.parent.ts - - object-member - - begin - [a-zA-Z_$][\w$]*\s*: - end - (?=,|\}) - name - meta.object.member.ts - patterns - - - include - #expression - - - - object-name - - captures - - 0 - - name - entity.name.class.ts - - - match - [a-zA-Z_$][\w$]* - name - meta.object.name.ts - - parameter-name - - captures - - 1 - - name - storage.modifier.ts - - 2 - - name - keyword.operator.ts - - 3 - - name - variable.parameter.ts - - 4 - - name - keyword.operator.ts - - - match - (?:\s*\b(public|private|protected)\b\s+)?(\.\.\.)?\s*([a-zA-Z_$][\w$]*)\s*(\??) - name - parameter.name.ts - - paren-expression - - begin - \( - beginCaptures - - 0 - - name - meta.brace.paren.ts - - - end - \) - endCaptures - - 0 - - name - meta.brace.paren.ts - - - patterns - - - include - #expression - - - - property-accessor - - match - \b(get|set)\b - name - storage.type.property.ts - - qstring-double - - begin - " - end - "|(?=$) - name - string.double.ts - patterns - - - include - #string-character-escape - - - - qstring-single - - begin - ' - end - '|(?=$) - name - string.single.ts - patterns - - - include - #string-character-escape - - - - regex - - begin - (?<=[=(:,\[]|^|return|&&|\|\||!)\s*(/)(?![/*+{}?]) - end - $|(/)[igm]* - name - string.regex.ts - patterns - - - match - \\. - name - constant.character.escape.ts - - - match - \[(\\\]|[^\]])*\] - name - constant.character.class.ts - - - - relational-operator - - match - ===|==|=|!=|!==|<=|>=|<>|<|> - name - keyword.operator.comparison.ts - - return-type - - begin - (?<=\))\s*: - end - (?=$)|(?=\{|;|//) - name - meta.return.type.ts - patterns - - - include - #type - - - - static-modifier - - match - \b(static)\b - name - keyword.other.ts - - storage-keyword - - match - \b(number|boolean|string|any|var|let|function|const)\b - name - storage.type.ts - - string - - name - string.ts - patterns - - - include - #qstring-single - - - include - #qstring-double - - - - string-character-escape - - match - \\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.|$) - name - constant.character.escape - - switch-case - - begin - (?<!\.)\b(case|default)\b - beginCaptures - - 1 - - name - keyword.control.ts - - - end - : - name - case.expr.ts - patterns - - - include - #expression - - - - template - - begin - ` - beginCaptures - - 0 - - name - string.template.ts - - - end - ` - endCaptures - - 0 - - name - string.template.ts - - - name - meta.template.ts - patterns - - - include - #template-substitution-element - - - include - #template-string-contents - - - - template-string-contents - - begin - .*? - end - (?=(\$\{|`)) - name - string.template.ts - patterns - - - include - #string-character-escape - - - - template-substitution-element - - begin - \$\{ - beginCaptures - - 0 - - name - keyword.operator.ts - - - end - \} - endCaptures - - 0 - - name - keyword.operator.ts - - - name - template.element.ts - patterns - - - include - #expression - - - - this-literal - - match - \b(this)\b - name - constant.language.this.ts - - type - - name - meta.type.ts - patterns - - - include - #type-primitive - - - include - #type-parameters - - - include - #type-tuple - - - include - #type-object - - - include - #type-operator - - - include - #type-paren-or-function-type-parameters - - - include - #type-function-return-type - - - include - #type-name - - - - type-annotation - - begin - : - end - (?=$|[,);\}\]]|//)|(?==[^>])|(?<=[\}>\]\)]|[a-zA-Z_$])\s*(?=\{) - name - meta.type.annotation.ts - patterns - - - include - #type - - - include - #string - - - include - #comment - - - - type-declaration - - begin - \b(type)\b\s+([a-zA-Z_$][\w$]*)\s*=\s* - beginCaptures - - 1 - - name - keyword.other.ts - - 2 - - name - storage.type.ts - - - end - (?=[,);>]|var|type|function|class|interface) - name - meta.type.declaration.ts - patterns - - - include - #type - - - - type-function-return-type - - begin - => - beginCaptures - - 0 - - name - keyword.operator.ts - - - end - (?=\s*[,\)\{=;>]|//|$) - name - meta.type.function.return.ts - patterns - - - include - #type - - - - type-name - - captures - - 1 - - name - entity.name.type.ts - - - match - [a-zA-Z_$][.\w$]* - name - meta.type.name.ts - - type-object - - begin - \{ - beginCaptures - - 0 - - name - meta.brace.curly.ts - - - end - \} - endCaptures - - 0 - - name - meta.brace.curly.ts - - - name - meta.object.type.ts - patterns - - - include - #comment - - - include - #field-declaration - - - include - #method-declaration - - - include - #indexer-declaration - - - include - #type-annotation - - - - type-operator - - match - [.|] - name - keyword.operator.type.ts - - type-parameters - - begin - ([a-zA-Z_$][\w$]*)?(<) - beginCaptures - - 1 - - name - entity.name.type.ts - - 2 - - name - meta.brace.angle.ts - - - end - (?=$)|(>) - endCaptures - - 2 - - name - meta.brace.angle.ts - - - name - meta.type.parameters.ts - patterns - - - match - \b(extends)\b - name - keyword.other.ts - - - include - #comment - - - include - #type - - - - type-paren-or-function-type-parameters - - begin - (?:\b(new)\b)?\s*\( - beginCaptures - - 1 - - name - keyword.control.ts - - - end - \) - name - meta.type.paren.cover.ts - patterns - - - include - #comment - - - include - #type - - - include - #function-type-parameters - - - - type-primitive - - captures - - 1 - - name - storage.type.ts - - - match - \b(string|number|boolean|symbol|any|void)\b - name - meta.type.primitive.ts - - type-tuple - - begin - \[ - beginCaptures - - 0 - - name - meta.brace.square.ts - - - end - \] - endCaptures - - 0 - - name - meta.brace.square.ts - - - name - meta.type.tuple.ts - patterns - - - include - #type - - - include - #comment - - - - undefined-literal - - match - \b(undefined)\b - name - constant.language.ts - - var-expr - - begin - (?<!\()\s*\b(var|let|const(?!\s+enum))\s+([a-zA-Z_$][\w$]*) - beginCaptures - - 1 - - name - storage.type.ts - - 2 - - name - variable.ts - - - end - (?=$|[;=\}\{])|(?<=\}) - name - meta.var.expr.ts - patterns - - - include - #type-annotation - - - include - #string - - - include - #comment - - - - variable-initializer - - begin - (=) - beginCaptures - - 1 - - name - keyword.operator.ts - - - end - (?=$|[,);=]) - patterns - - - include - #expression - - - - - scopeName - source.ts - uuid - ef98eb90-bf9b-11e4-bb52-0800200c9a66 - + + + + + fileTypes + + ts + + name + TypeScript + patterns + + + include + #expression + + + repository + + access-modifier + + match + \b(public|protected|private)\b + name + storage.modifier.ts + + arithmetic-operator + + match + \*|/|\-\-|\-|\+\+|\+|% + name + keyword.operator.arithmetic.ts + + array-literal + + begin + \[ + beginCaptures + + 0 + + name + meta.brace.square.ts + + + end + \] + endCaptures + + 0 + + name + meta.brace.square.ts + + + name + meta.array.literal.ts + patterns + + + include + #expression + + + + assignment-operator + + match + <<=|>>=|>>>=|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^= + name + keyword.operator.assignment.ts + + block + + begin + \{ + beginCaptures + + 0 + + name + meta.brace.curly.ts + + + end + \} + endCaptures + + 0 + + name + meta.brace.curly.ts + + + name + meta.block.ts + patterns + + + include + #expression + + + include + #object-member + + + + boolean-literal + + match + \b(false|true)\b + name + constant.language.boolean.ts + + cast + + begin + (?:(?<=return|throw|yield|[=(,:>]))\s*(<)(?!<?\=) + beginCaptures + + 1 + + name + meta.brace.angle.ts + + + end + > + endCaptures + + 0 + + name + meta.brace.angle.ts + + + name + cast.expr.ts + patterns + + + include + #type + + + + comment + + name + comment.ts + patterns + + + include + #comment-block-doc + + + include + #comment-block + + + include + #comment-line + + + + comment-block + + begin + /\* + end + \*/ + name + comment.block.ts + + comment-block-doc + + begin + /\*\*(?!/) + end + \*/ + name + comment.block.documentation.ts + + comment-line + + match + (//).*$\n? + name + comment.line.ts + + control-statement + + match + (?<!\.)\b(break|catch|continue|debugger|declare|do|else|finally|for|if|return|switch|throw|try|while|with|super|case|default)\b + name + keyword.control.ts + + decl-block + + begin + \{ + beginCaptures + + 0 + + name + meta.brace.curly.ts + + + end + \} + endCaptures + + 0 + + name + meta.brace.curly.ts + + + name + meta.decl.block.ts + patterns + + + include + #expression + + + + declaration + + name + meta.declaration.ts + patterns + + + include + #function-declaration + + + include + #object-declaration + + + include + #type-declaration + + + include + #enum-declaration + + + + enum-declaration + + captures + + 1 + + name + storage.modifier.ts + + 2 + + name + storage.type.ts + + 3 + + name + entity.name.class.ts + + + match + (?:\b(const)\s+)?\b(enum)\s+([a-zA-Z_$][\w$]*) + name + meta.enum.declaration.ts + + expression + + name + meta.expression.ts + patterns + + + include + #ngTemplate + + + include + #for-in-simple + + + include + #string + + + include + #regex + + + include + #template + + + include + #comment + + + include + #literal + + + include + #paren-expression + + + include + #var-expr + + + include + #declaration + + + include + #cast + + + include + #new-expr + + + include + #block + + + include + #expression-operator + + + include + #relational-operator + + + include + #arithmetic-operator + + + include + #logic-operator + + + include + #assignment-operator + + + include + #storage-keyword + + + include + #function-call + + + include + #switch-case + + + include + #control-statement + + + + expression-operator + + match + =>|\b(delete|export|import|in|instanceof|module|namespace|new|typeof|void)\b + name + keyword.operator.ts + + field-declaration + + begin + (?<!\()\s*\b([a-zA-Z_$][\w$]*)\s*(\?\s*)?(?=(=|:)) + beginCaptures + + 1 + + name + variable.ts + + 2 + + name + keyword.operator.ts + + + end + (?=\}|;|,)|(?<=\}) + name + meta.field.declaration.ts + patterns + + + include + #expression + + + + for-in-simple + + captures + + 1 + + name + storage.type.ts + + 3 + + name + keyword.operator.ts + + + match + (?<=\()\s*\b(var|let|const)\s+([a-zA-Z_$][\w$]*)\s+(in|of)\b + name + forin.expr.ts + + function-call + + name + functioncall.expr.ts + patterns + + + include + #type-parameters + + + include + #paren-expression + + + + function-declaration + + begin + \b(?:(export)\s+)?(function\b)(?:\s+([a-zA-Z_$][\w$]*))?\s* + beginCaptures + + 1 + + name + storage.modifier.ts + + 2 + + name + storage.type.function.ts + + 3 + + name + entity.name.function.ts + + + end + (?=;|\})|(?<=\}) + name + meta.function.ts + patterns + + + include + #comment + + + include + #type-parameters + + + include + #function-type-parameters + + + include + #return-type + + + include + #function-overload-declaration + + + include + #decl-block + + + + function-overload-declaration + + captures + + 1 + + name + storage.modifier.ts + + 2 + + name + storage.type.function.ts + + 3 + + name + entity.name.function.ts + + + match + \b(?:(export)\s+)?(function\b)(?:\s+([a-zA-Z_$][\w$]*))?\s* + name + meta.function.overload.ts + + function-type-parameters + + begin + \( + beginCaptures + + 0 + + name + meta.brace.round.ts + + + end + \) + endCaptures + + 0 + + name + meta.brace.round.ts + + + name + meta.function.type.parameter.ts + patterns + + + include + #comment + + + include + #parameter-name + + + include + #type-annotation + + + include + #variable-initializer + + + + htmlComment + + begin + <!-- + end + --> + name + comment.block.ts + + htmlText + + match + .*?(?=({{)|(\$\{)|<|$) + name + string.ts + + indexer-declaration + + begin + \[ + beginCaptures + + 0 + + name + meta.brace.square.ts + + + end + (\])\s*(\?\s*)?|$ + endCaptures + + 1 + + name + meta.brace.square.ts + + 2 + + name + keyword.operator.ts + + + name + meta.indexer.declaration.ts + patterns + + + include + #type-annotation + + + include + #indexer-parameter + + + include + #expression + + + + indexer-parameter + + captures + + 1 + + name + variable.parameter.ts + + + match + ([a-zA-Z_$][\w$]*)(?=\:) + name + meta.indexer.parameter.ts + + literal + + name + literal.ts + patterns + + + include + #numeric-literal + + + include + #boolean-literal + + + include + #null-literal + + + include + #undefined-literal + + + include + #array-literal + + + include + #this-literal + + + + logic-operator + + match + \!|&|~|\||&&|\|\| + name + keyword.operator.arithmetic.ts + + method-declaration + + begin + \b(?:(abstract)\s+)?\b(?:(public|private|protected)\s+)?(?:(get|set)\s+)?(?:(new)|(?:([a-zA-Z_$][\.\w$]*)\s*(\??)))?\s*(?=\(|\<) + beginCaptures + + 1 + + name + storage.modifier.ts + + 2 + + name + storage.modifier.ts + + 3 + + name + storage.type.property.ts + + 4 + + name + keyword.operator.ts + + 5 + + name + entity.name.function.ts + + 6 + + name + keyword.operator.ts + + + end + (?=\}|;|,)|(?<=\}) + name + meta.method.declaration.ts + patterns + + + include + #comment + + + include + #type-parameters + + + include + #function-type-parameters + + + include + #type-annotation + + + include + #method-overload-declaration + + + include + #decl-block + + + + method-overload-declaration + + captures + + 1 + + name + storage.modifier.ts + + 2 + + name + keyword.operator.ts + + 3 + + name + entity.name.function.ts + + 4 + + name + keyword.operator.ts + + + match + \b(?:(public|private|protected)\s+)?(?:(new)|(?:([a-zA-Z_$][\.\w$]*)\s*(\??)))?\s*(?=\(|\<) + name + meta.method.overload.declaration.ts + + new-expr + + begin + \b(new)\b + beginCaptures + + 1 + + name + keyword.operator.ts + + + end + (?=[(;]|$) + name + new.expr.ts + patterns + + + include + #type + + + include + #comment + + + + ngAttrib + + begin + ([a-zA-Z\$][a-zA-Z0-9\$\-]*) + beginCaptures + + 1 + + name + entity.name.class.ts + + + end + (?=[^'=]) + name + meta.attribute.ts + patterns + + + include + #ngAttribValue + + + + ngAttribValue + + begin + = + beginCaptures + + 0 + + name + punctuation.separator.key-value.ts + + + end + (?<=') + name + meta.attribute.ts + patterns + + + include + #qstring-single + + + + ngBinding + + begin + (?:\(|\[|(?:\[\())([a-zA-Z\$][a-zA-Z0-9\$\-]*)(?:(?:\)\])|\)|\]) + beginCaptures + + 1 + + name + keyword.control.ts + + + end + (?=[^'=]) + name + meta.binding-name.ts + patterns + + + include + #ngAttribValue + + + + ngDirective + + begin + \*([a-zA-Z\$][a-zA-Z0-9\$\-]*) + beginCaptures + + 1 + + name + keyword.control.ts + + + end + (?=[^'=]) + name + meta.directive-name.ts + patterns + + + include + #ngAttribValue + + + + ngExpr + + begin + {{ + beginCaptures + + 0 + + name + keyword.operator.ts + + + end + }} + endCaptures + + 0 + + name + keyword.operator.ts + + + name + meta.expression.ts + patterns + + + include + #expression + + + + ngTag + + begin + (<)([a-zA-Z\$][a-zA-Z0-9\$\-]*) + beginCaptures + + 1 + + name + keyword.operator.ts + + 2 + + name + entity.name.tag.ts + + + end + (/>)|(?:(</)([a-zA-Z\$][a-zA-Z0-9\$\-]*)(>)) + endCaptures + + 1 + + name + keyword.operator.ts + + 2 + + name + keyword.operator.ts + + 3 + + name + entity.name.tag.ts + + 4 + + name + keyword.operator.ts + + + name + meta.tag.ts + patterns + + + include + #ngAttrib + + + include + #ngDirective + + + include + #ngBinding + + + include + #ngTagEnd + + + + ngTagEnd + + begin + > + beginCaptures + + 0 + + name + keyword.operator.ts + + + end + (?=</) + name + meta.tagend.ts + patterns + + + include + #ngml + + + + ngTemplate + + begin + (?:(?<=^|\stemplate:)|(?<=/\*\* @html \*/))\s*(`) + beginCaptures + + 1 + + name + string.template.ts + + + end + ` + endCaptures + + 0 + + name + string.template.ts + + + name + meta.ngTemplate.ts + patterns + + + include + #ngml + + + + ngml + + name + meta.ngml.ts + patterns + + + include + #ngTag + + + include + #ngExpr + + + include + #htmlComment + + + include + #template-substitution-element + + + include + #htmlText + + + + null-literal + + match + \b(null)\b + name + constant.language.null.ts + + numeric-literal + + match + \b(?<=[^$])((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?))\b + name + constant.numeric.ts + + object-body + + begin + \{ + beginCaptures + + 0 + + name + meta.brace.curly.ts + + + end + \} + endCaptures + + 0 + + name + meta.brace.curly.ts + + + name + meta.object.body.ts + patterns + + + include + #string + + + include + #comment + + + include + #field-declaration + + + include + #method-declaration + + + include + #indexer-declaration + + + include + #type-annotation + + + include + #variable-initializer + + + include + #access-modifier + + + include + #static-modifier + + + include + #property-accessor + + + + object-declaration + + begin + \b(?:(export)\s+)?\b(?:(abstract)\s+)?\b(?<!\.)(class|interface)\b + beginCaptures + + 1 + + name + storage.modifier.ts + + 2 + + name + storage.modifier.ts + + 3 + + name + storage.type.ts + + + end + (?<=\}) + endCaptures + + 1 + + name + brace.curly.ts + + + name + meta.declaration.object.ts + patterns + + + include + #comment + + + include + #object-heritage + + + include + #object-name + + + include + #type-parameters + + + include + #object-body + + + + object-heritage + + begin + (?:\b(extends|implements)) + beginCaptures + + 1 + + name + keyword.other.ts + + + end + (?=\{) + endCaptures + + 1 + + name + brace.curly.ts + + + name + meta.object.heritage.ts + patterns + + + include + #comment + + + include + #type-parameters + + + include + #object-heritage-parent + + + + object-heritage-parent + + captures + + 1 + + name + storage.type.ts + + + match + (?:\s*([a-zA-Z_$][\w$]*)) + name + meta.object.heritage.parent.ts + + object-member + + begin + [a-zA-Z_$][\w$]*\s*: + end + (?=,|\}) + name + meta.object.member.ts + patterns + + + include + #expression + + + + object-name + + captures + + 0 + + name + entity.name.class.ts + + + match + [a-zA-Z_$][\w$]* + name + meta.object.name.ts + + parameter-name + + captures + + 1 + + name + storage.modifier.ts + + 2 + + name + keyword.operator.ts + + 3 + + name + variable.parameter.ts + + 4 + + name + keyword.operator.ts + + + match + (?:\s*\b(public|private|protected)\b\s+)?(\.\.\.)?\s*([a-zA-Z_$][\w$]*)\s*(\??) + name + parameter.name.ts + + paren-expression + + begin + \( + beginCaptures + + 0 + + name + meta.brace.paren.ts + + + end + \) + endCaptures + + 0 + + name + meta.brace.paren.ts + + + patterns + + + include + #expression + + + + property-accessor + + match + \b(get|set)\b + name + storage.type.property.ts + + qstring-double + + begin + " + end + "|(?=$) + name + string.double.ts + patterns + + + include + #string-character-escape + + + + qstring-single + + begin + ' + end + '|(?=$) + name + string.single.ts + patterns + + + include + #string-character-escape + + + + regex + + begin + (?<=[=(:,\[]|^|return|&&|\|\||!)\s*(/)(?![/*+{}?]) + end + $|(/)[igm]* + name + string.regex.ts + patterns + + + match + \\. + name + constant.character.escape.ts + + + match + \[(\\\]|[^\]])*\] + name + constant.character.class.ts + + + + relational-operator + + match + ===|==|=|!=|!==|<=|>=|<>|<|> + name + keyword.operator.comparison.ts + + return-type + + begin + (?<=\))\s*: + end + (?=$)|(?=\{|;|//) + name + meta.return.type.ts + patterns + + + include + #type + + + + static-modifier + + match + \b(static)\b + name + keyword.other.ts + + storage-keyword + + match + \b(number|boolean|string|any|var|let|function|const)\b + name + storage.type.ts + + string + + name + string.ts + patterns + + + include + #qstring-single + + + include + #qstring-double + + + + string-character-escape + + match + \\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.|$) + name + constant.character.escape + + switch-case + + begin + (?<!\.)\b(case|default)\b + beginCaptures + + 1 + + name + keyword.control.ts + + + end + : + name + case.expr.ts + patterns + + + include + #expression + + + + template + + begin + ` + beginCaptures + + 0 + + name + string.template.ts + + + end + ` + endCaptures + + 0 + + name + string.template.ts + + + name + meta.template.ts + patterns + + + include + #template-substitution-element + + + include + #template-string-contents + + + + template-string-contents + + begin + .*? + end + (?=(\$\{|`)) + name + string.template.ts + patterns + + + include + #string-character-escape + + + + template-substitution-element + + begin + \$\{ + beginCaptures + + 0 + + name + keyword.operator.ts + + + end + \} + endCaptures + + 0 + + name + keyword.operator.ts + + + name + template.element.ts + patterns + + + include + #expression + + + + this-literal + + match + \b(this)\b + name + constant.language.this.ts + + type + + name + meta.type.ts + patterns + + + include + #type-primitive + + + include + #type-parameters + + + include + #type-tuple + + + include + #type-object + + + include + #type-operator + + + include + #type-paren-or-function-type-parameters + + + include + #type-function-return-type + + + include + #type-name + + + + type-annotation + + begin + : + end + (?=$|[,);\}\]]|//)|(?==[^>])|(?<=[\}>\]\)]|[a-zA-Z_$])\s*(?=\{) + name + meta.type.annotation.ts + patterns + + + include + #type + + + include + #string + + + include + #comment + + + + type-declaration + + begin + \b(type)\b\s+([a-zA-Z_$][\w$]*)\s*=\s* + beginCaptures + + 1 + + name + keyword.other.ts + + 2 + + name + storage.type.ts + + + end + (?=[,);>]|var|type|function|class|interface) + name + meta.type.declaration.ts + patterns + + + include + #type + + + + type-function-return-type + + begin + => + beginCaptures + + 0 + + name + keyword.operator.ts + + + end + (?=\s*[,\)\{=;>]|//|$) + name + meta.type.function.return.ts + patterns + + + include + #type + + + + type-name + + captures + + 1 + + name + entity.name.type.ts + + + match + [a-zA-Z_$][.\w$]* + name + meta.type.name.ts + + type-object + + begin + \{ + beginCaptures + + 0 + + name + meta.brace.curly.ts + + + end + \} + endCaptures + + 0 + + name + meta.brace.curly.ts + + + name + meta.object.type.ts + patterns + + + include + #comment + + + include + #field-declaration + + + include + #method-declaration + + + include + #indexer-declaration + + + include + #type-annotation + + + + type-operator + + match + [.|] + name + keyword.operator.type.ts + + type-parameters + + begin + ([a-zA-Z_$][\w$]*)?(<) + beginCaptures + + 1 + + name + entity.name.type.ts + + 2 + + name + meta.brace.angle.ts + + + end + (?=$)|(>) + endCaptures + + 2 + + name + meta.brace.angle.ts + + + name + meta.type.parameters.ts + patterns + + + match + \b(extends)\b + name + keyword.other.ts + + + include + #comment + + + include + #type + + + + type-paren-or-function-type-parameters + + begin + (?:\b(new)\b)?\s*\( + beginCaptures + + 1 + + name + keyword.control.ts + + + end + \) + name + meta.type.paren.cover.ts + patterns + + + include + #comment + + + include + #type + + + include + #function-type-parameters + + + + type-primitive + + captures + + 1 + + name + storage.type.ts + + + match + \b(string|number|boolean|symbol|any|void)\b + name + meta.type.primitive.ts + + type-tuple + + begin + \[ + beginCaptures + + 0 + + name + meta.brace.square.ts + + + end + \] + endCaptures + + 0 + + name + meta.brace.square.ts + + + name + meta.type.tuple.ts + patterns + + + include + #type + + + include + #comment + + + + undefined-literal + + match + \b(undefined)\b + name + constant.language.ts + + var-expr + + begin + (?<!\()\s*\b(var|let|const(?!\s+enum))\s+([a-zA-Z_$][\w$]*) + beginCaptures + + 1 + + name + storage.type.ts + + 2 + + name + variable.ts + + + end + (?=$|[;=\}\{])|(?<=\}) + name + meta.var.expr.ts + patterns + + + include + #type-annotation + + + include + #string + + + include + #comment + + + + variable-initializer + + begin + (=) + beginCaptures + + 1 + + name + keyword.operator.ts + + + end + (?=$|[,);=]) + patterns + + + include + #expression + + + + + scopeName + source.ts + uuid + ef98eb90-bf9b-11e4-bb52-0800200c9a66 + \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/JavaScript.tmLanguage.json b/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/JavaScript.tmLanguage.json new file mode 100644 index 000000000..7bc39946d --- /dev/null +++ b/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/JavaScript.tmLanguage.json @@ -0,0 +1,1415 @@ +{ + "fileTypes": [ + "js", + "jsx" + ], + "name": "JavaScript (with React support)", + "patterns": [ + { + "include": "#expression" + } + ], + "repository": { + "access-modifier": { + "match": "\\b(public|protected|private)\\b", + "name": "storage.modifier.js" + }, + "arithmetic-operator": { + "match": "\\*|\/|\\-\\-|\\-|\\+\\+|\\+|%", + "name": "keyword.operator.arithmetic.js" + }, + "array-literal": { + "begin": "\\[", + "beginCaptures": { + "0": { + "name": "meta.brace.square.js" + } + }, + "end": "\\]", + "endCaptures": { + "0": { + "name": "meta.brace.square.js" + } + }, + "name": "meta.array.literal.js", + "patterns": [ + { + "include": "#expression" + } + ] + }, + "assignment-operator": { + "match": "<<=|>>=|>>>=|\\*=|(?|\\b(delete|export|import|from|in|instanceof|new|typeof|void|as)\\b", + "name": "keyword.operator.js" + }, + "field-declaration": { + "begin": "(?)", + "end": "(?=<\/)", + "name": "meta.jsx.children.js", + "patterns": [ + { + "include": "#jsx-children" + } + ] + } + ] + }, + "jsx-children": { + "patterns": [ + { + "include": "#jsx-tag-without-attributes" + }, + { + "include": "#jsx-tag-open" + }, + { + "include": "#jsx-tag-close" + }, + { + "include": "#jsx-tag-invalid" + }, + { + "include": "#jsx-evaluated-code" + }, + { + "include": "#jsx-entities" + } + ] + }, + "jsx-entities": { + "patterns": [ + { + "captures": { + "1": { + "name": "punctuation.definition.entity.js" + }, + "3": { + "name": "punctuation.definition.entity.js" + } + }, + "match": "(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)", + "name": "constant.character.entity.js" + }, + { + "match": "&", + "name": "invalid.illegal.bad-ampersand.js" + } + ] + }, + "jsx-evaluated-code": { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.brace.curly.start.js" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.definition.brace.curly.end.js" + } + }, + "name": "meta.brace.curly.js", + "patterns": [ + { + "include": "#expression" + } + ] + }, + "jsx-string-double-quoted": { + "begin": "\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.js" + } + }, + "end": "\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.js" + } + }, + "name": "string.quoted.double.js", + "patterns": [ + { + "include": "#jsx-entities" + } + ] + }, + "jsx-string-single-quoted": { + "begin": "'", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.js" + } + }, + "end": "'", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.js" + } + }, + "name": "string.quoted.single.js", + "patterns": [ + { + "include": "#jsx-entities" + } + ] + }, + "jsx-tag-attribute-assignment": { + "match": "=(?=\\s*(?:'|\"|{|\/\\*|\/\/|\\n))", + "name": "keyword.operator.assignment.js" + }, + "jsx-tag-attribute-name": { + "captures": { + "1": { + "name": "entity.other.attribute-name.js" + } + }, + "match": "(?x)\n \\s*\n ([_$a-zA-Z][-$\\w]*)\n (?=\\s|=|\/?>|\/\\*|\/\/)", + "name": "meta.tag.attribute-name.js" + }, + "jsx-tag-attributes": { + "patterns": [ + { + "include": "#jsx-tag-attribute-name" + }, + { + "include": "#jsx-tag-attribute-assignment" + }, + { + "include": "#jsx-string-double-quoted" + }, + { + "include": "#jsx-string-single-quoted" + }, + { + "include": "#jsx-evaluated-code" + } + ] + }, + "jsx-tag-attributes-illegal": { + "match": "\\S+", + "name": "invalid.illegal.attribute.js" + }, + "jsx-tag-close": { + "begin": "(<\/)([_$a-zA-Z][-$\\w.]*(?)", + "endCaptures": { + "1": { + "name": "punctuation.definition.tag.end.js" + } + }, + "name": "tag.close.js", + "patterns": [ + { + "include": "#comment" + } + ] + }, + "jsx-tag-invalid": { + "match": "<\\s*>", + "name": "invalid.illegal.tag.incomplete.js" + }, + "jsx-tag-open": { + "begin": "(?x)\n (<)\n ([_$a-zA-Z][-$\\w.]*(?)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.js" + }, + "2": { + "name": "entity.name.tag.js" + } + }, + "end": "(\/?>)", + "endCaptures": { + "1": { + "name": "punctuation.definition.tag.end.js" + } + }, + "name": "tag.open.js", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#jsx-tag-attributes" + }, + { + "include": "#jsx-tag-attributes-illegal" + } + ] + }, + "jsx-tag-without-attributes": { + "begin": "(<)([_$a-zA-Z][-$\\w.]*(?)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.js" + }, + "2": { + "name": "entity.name.tag.js" + }, + "3": { + "name": "punctuation.definition.tag.end.js" + } + }, + "end": "(<\/)([_$a-zA-Z][-$\\w.]*(?)", + "endCaptures": { + "1": { + "name": "punctuation.definition.tag.begin.js" + }, + "2": { + "name": "entity.name.tag.js" + }, + "3": { + "name": "punctuation.definition.tag.end.js" + } + }, + "name": "tag.without-attributes.js", + "patterns": [ + { + "include": "#jsx-children" + } + ] + }, + "literal": { + "name": "literal.js", + "patterns": [ + { + "include": "#numeric-literal" + }, + { + "include": "#boolean-literal" + }, + { + "include": "#null-literal" + }, + { + "include": "#undefined-literal" + }, + { + "include": "#array-literal" + }, + { + "include": "#this-literal" + } + ] + }, + "logic-operator": { + "match": "\\!|&|~|\\||&&|\\|\\|", + "name": "keyword.operator.arithmetic.js" + }, + "method-declaration": { + "begin": "\\b(?:(abstract)\\s+)?\\b(?:(public|private|protected)\\s+)?\\b(?:(async)\\s+)?(?:(get|set)\\s+)?(?:(new)|(?:([a-zA-Z_$][\\.\\w$]*)\\s*(\\??)))?\\s*(?=\\(|\\<)", + "beginCaptures": { + "1": { + "name": "storage.modifier.js" + }, + "2": { + "name": "storage.modifier.js" + }, + "3": { + "name": "storage.modifier.js" + }, + "4": { + "name": "storage.type.property.js" + }, + "5": { + "name": "keyword.operator.js" + }, + "6": { + "name": "entity.name.function.js" + }, + "7": { + "name": "keyword.operator.js" + } + }, + "end": "(?=\\}|;|,)|(?<=\\})", + "name": "meta.method.declaration.js", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#type-parameters" + }, + { + "include": "#function-type-parameters" + }, + { + "include": "#type-annotation" + }, + { + "include": "#method-overload-declaration" + }, + { + "include": "#decl-block" + } + ] + }, + "method-overload-declaration": { + "captures": { + "1": { + "name": "storage.modifier.js" + }, + "2": { + "name": "storage.modifier.js" + }, + "3": { + "name": "storage.modifier.js" + }, + "4": { + "name": "storage.type.property.js" + }, + "5": { + "name": "keyword.operator.js" + }, + "6": { + "name": "entity.name.function.js" + }, + "7": { + "name": "keyword.operator.js" + } + }, + "match": "\\b(?:(abstract)\\s+)?\\b(?:(public|private|protected)\\s+)?\\b(?:(async)\\s+)?(?:(get|set)\\s+)?(?:(new)|(?:([a-zA-Z_$][\\.\\w$]*)\\s*(\\??)))?\\s*(?=\\(|\\<)", + "name": "meta.method.overload.declaration.js" + }, + "new-expr": { + "begin": "\\b(new)\\b", + "beginCaptures": { + "1": { + "name": "keyword.operator.js" + } + }, + "end": "(?=[(;]|$)", + "name": "new.expr.js", + "patterns": [ + { + "include": "#type" + }, + { + "include": "#comment" + } + ] + }, + "null-literal": { + "match": "\\b(null)\\b", + "name": "constant.language.null.js" + }, + "numeric-literal": { + "match": "\\b(?<=[^$])((0(x|X)[0-9a-fA-F]+)|([0-9]+(\\.[0-9]+)?))\\b", + "name": "constant.numeric.js" + }, + "object-body": { + "begin": "\\{", + "beginCaptures": { + "0": { + "name": "meta.brace.curly.js" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "meta.brace.curly.js" + } + }, + "name": "meta.object.body.js", + "patterns": [ + { + "include": "#string" + }, + { + "include": "#comment" + }, + { + "include": "#field-declaration" + }, + { + "include": "#method-declaration" + }, + { + "include": "#indexer-declaration" + }, + { + "include": "#type-annotation" + }, + { + "include": "#variable-initializer" + }, + { + "include": "#access-modifier" + }, + { + "include": "#static-modifier" + }, + { + "include": "#property-accessor" + } + ] + }, + "object-declaration": { + "begin": "\\b(?:(export)\\s+)?\\b(?:(abstract)\\s+)?\\b(?=|<>|<|>", + "name": "keyword.operator.comparison.js" + }, + "return-type": { + "begin": "(?<=\\))\\s*:", + "end": "(?=$)|(?=\\{|;|\/\/)", + "name": "meta.return.type.js", + "patterns": [ + { + "include": "#type" + } + ] + }, + "static-modifier": { + "match": "\\b(static)\\b", + "name": "keyword.other.js" + }, + "storage-keyword": { + "match": "\\b(number|boolean|string|any|var|let|function|const|module|namespace)\\b", + "name": "storage.type.js" + }, + "string": { + "name": "string.js", + "patterns": [ + { + "include": "#qstring-single" + }, + { + "include": "#qstring-double" + } + ] + }, + "string-character-escape": { + "match": "\\\\(x\\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.|$)", + "name": "constant.character.escape" + }, + "switch-block": { + "begin": "{", + "end": "(?=\\})", + "name": "switch-block.expr.js", + "patterns": [ + { + "include": "#expression" + } + ] + }, + "switch-expression": { + "begin": "\\b(switch)\\b\\s*\\(", + "beginCaptures": { + "1": { + "name": "keyword.operator.js" + } + }, + "end": "\\)", + "name": "switch-expression.expr.js", + "patterns": [ + { + "include": "#expression" + } + ] + }, + "switch-statement": { + "begin": "(?=\\bswitch\\b\\s*\\()", + "end": "}", + "name": "switch-statement.expr.js", + "patterns": [ + { + "include": "#switch-expression" + }, + { + "include": "#switch-block" + } + ] + }, + "template": { + "begin": "`", + "beginCaptures": { + "0": { + "name": "string.template.js" + } + }, + "end": "`", + "endCaptures": { + "0": { + "name": "string.template.js" + } + }, + "name": "meta.template.js", + "patterns": [ + { + "include": "#template-substitution-element" + }, + { + "include": "#template-string-contents" + } + ] + }, + "template-string-contents": { + "begin": ".*?", + "end": "(?=(\\$\\{|`))", + "name": "string.template.js", + "patterns": [ + { + "include": "#string-character-escape" + } + ] + }, + "template-substitution-element": { + "begin": "\\$\\{", + "beginCaptures": { + "0": { + "name": "keyword.operator.js" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "keyword.operator.js" + } + }, + "name": "template.element.js", + "patterns": [ + { + "include": "#expression" + } + ] + }, + "this-literal": { + "match": "\\b(this)\\b", + "name": "constant.language.this.js" + }, + "type": { + "name": "meta.type.js", + "patterns": [ + { + "include": "#type-primitive" + }, + { + "include": "#type-parameters" + }, + { + "include": "#type-tuple" + }, + { + "include": "#type-object" + }, + { + "include": "#type-operator" + }, + { + "include": "#type-paren-or-function-type-parameters" + }, + { + "include": "#type-function-return-type" + }, + { + "include": "#type-name" + } + ] + }, + "type-annotation": { + "begin": ":", + "end": "(?=$|[,);\\}\\]]|\/\/)|(?==[^>])|(?<=[\\}>\\]\\)]|[a-zA-Z_$])\\s*(?=\\{)", + "name": "meta.type.annotation.js", + "patterns": [ + { + "include": "#type" + }, + { + "include": "#string" + }, + { + "include": "#comment" + } + ] + }, + "type-declaration": { + "begin": "\\b(type)\\b\\s+([a-zA-Z_$][\\w$]*)\\s*=\\s*", + "beginCaptures": { + "1": { + "name": "keyword.other.js" + }, + "2": { + "name": "storage.type.js" + } + }, + "end": "(?=$|[,);>]|var|type|function|class|interface)", + "name": "meta.type.declaration.js", + "patterns": [ + { + "include": "#type" + } + ] + }, + "type-function-return-type": { + "begin": "=>", + "beginCaptures": { + "0": { + "name": "keyword.operator.js" + } + }, + "end": "(?=\\s*[,\\)\\{=;>]|\/\/|$)", + "name": "meta.type.function.return.js", + "patterns": [ + { + "include": "#type" + } + ] + }, + "type-name": { + "captures": { + "1": { + "name": "entity.name.type.js" + } + }, + "match": "[a-zA-Z_$][.\\w$]*", + "name": "meta.type.name.js" + }, + "type-object": { + "begin": "\\{", + "beginCaptures": { + "0": { + "name": "meta.brace.curly.js" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "meta.brace.curly.js" + } + }, + "name": "meta.object.type.js", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#field-declaration" + }, + { + "include": "#method-declaration" + }, + { + "include": "#indexer-declaration" + }, + { + "include": "#type-annotation" + } + ] + }, + "type-operator": { + "match": "[.|]", + "name": "keyword.operator.type.js" + }, + "type-parameters": { + "begin": "([a-zA-Z_$][\\w$]*)?(<)", + "beginCaptures": { + "1": { + "name": "entity.name.type.js" + }, + "2": { + "name": "meta.brace.angle.js" + } + }, + "end": "(?=$)|(>)", + "endCaptures": { + "2": { + "name": "meta.brace.angle.js" + } + }, + "name": "meta.type.parameters.js", + "patterns": [ + { + "match": "\\b(extends)\\b", + "name": "keyword.other.js" + }, + { + "include": "#comment" + }, + { + "include": "#type" + } + ] + }, + "type-paren-or-function-type-parameters": { + "begin": "(?:\\b(new)\\b)?\\s*\\(", + "beginCaptures": { + "1": { + "name": "keyword.control.js" + } + }, + "end": "\\)", + "name": "meta.type.paren.cover.js", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#type" + }, + { + "include": "#function-type-parameters" + } + ] + }, + "type-primitive": { + "captures": { + "1": { + "name": "storage.type.js" + } + }, + "match": "\\b(string|number|boolean|symbol|any|void)\\b", + "name": "meta.type.primitive.js" + }, + "type-tuple": { + "begin": "\\[", + "beginCaptures": { + "0": { + "name": "meta.brace.square.js" + } + }, + "end": "\\]", + "endCaptures": { + "0": { + "name": "meta.brace.square.js" + } + }, + "name": "meta.type.tuple.js", + "patterns": [ + { + "include": "#type" + }, + { + "include": "#comment" + } + ] + }, + "undefined-literal": { + "match": "\\b(undefined)\\b", + "name": "constant.language.js" + }, + "var-expr": { + "begin": "(?>=|>>>=|\\*=|(?|\\b(delete|export|import|from|in|instanceof|new|typeof|void|as)\\b" + name: keyword.operator.js + field-declaration: + begin: (?) + end: "(?=|/\*|//) + name: meta.tag.attribute-name.js + jsx-tag-attributes: + patterns: + - include: "#jsx-tag-attribute-name" + - include: "#jsx-tag-attribute-assignment" + - include: "#jsx-string-double-quoted" + - include: "#jsx-string-single-quoted" + - include: "#jsx-evaluated-code" + jsx-tag-attributes-illegal: + match: "\\S+" + name: invalid.illegal.attribute.js + jsx-tag-close: + begin: "()" + endCaptures: + '1': + name: punctuation.definition.tag.end.js + name: tag.close.js + patterns: + - include: "#comment" + jsx-tag-invalid: + match: "<\\s*>" + name: invalid.illegal.tag.incomplete.js + jsx-tag-open: + begin: |- + (?x) + (<) + ([_$a-zA-Z][-$\w.]*(?) + beginCaptures: + '1': + name: punctuation.definition.tag.begin.js + '2': + name: entity.name.tag.js + end: "(/?>)" + endCaptures: + '1': + name: punctuation.definition.tag.end.js + name: tag.open.js + patterns: + - include: "#comment" + - include: "#jsx-tag-attributes" + - include: "#jsx-tag-attributes-illegal" + jsx-tag-without-attributes: + begin: "(<)([_$a-zA-Z][-$\\w.]*(?)" + beginCaptures: + '1': + name: punctuation.definition.tag.begin.js + '2': + name: entity.name.tag.js + '3': + name: punctuation.definition.tag.end.js + end: "()" + endCaptures: + '1': + name: punctuation.definition.tag.begin.js + '2': + name: entity.name.tag.js + '3': + name: punctuation.definition.tag.end.js + name: tag.without-attributes.js + patterns: + - include: "#jsx-children" + literal: + name: literal.js + patterns: + - include: "#numeric-literal" + - include: "#boolean-literal" + - include: "#null-literal" + - include: "#undefined-literal" + - include: "#array-literal" + - include: "#this-literal" + logic-operator: + match: "\\!|&|~|\\||&&|\\|\\|" + name: keyword.operator.arithmetic.js + method-declaration: + begin: "\\b(?:(abstract)\\s+)?\\b(?:(public|private|protected)\\s+)?\\b(?:(async)\\s+)?(?:(get|set)\\s+)?(?:(new)|(?:([a-zA-Z_$][\\.\\w$]*)\\s*(\\??)))?\\s*(?=\\(|\\<)" + beginCaptures: + '1': + name: storage.modifier.js + '2': + name: storage.modifier.js + '3': + name: storage.modifier.js + '4': + name: storage.type.property.js + '5': + name: keyword.operator.js + '6': + name: entity.name.function.js + '7': + name: keyword.operator.js + end: "(?=\\}|;|,)|(?<=\\})" + name: meta.method.declaration.js + patterns: + - include: "#comment" + - include: "#type-parameters" + - include: "#function-type-parameters" + - include: "#type-annotation" + - include: "#method-overload-declaration" + - include: "#decl-block" + method-overload-declaration: + captures: + '1': + name: storage.modifier.js + '2': + name: storage.modifier.js + '3': + name: storage.modifier.js + '4': + name: storage.type.property.js + '5': + name: keyword.operator.js + '6': + name: entity.name.function.js + '7': + name: keyword.operator.js + match: "\\b(?:(abstract)\\s+)?\\b(?:(public|private|protected)\\s+)?\\b(?:(async)\\s+)?(?:(get|set)\\s+)?(?:(new)|(?:([a-zA-Z_$][\\.\\w$]*)\\s*(\\??)))?\\s*(?=\\(|\\<)" + name: meta.method.overload.declaration.js + new-expr: + begin: "\\b(new)\\b" + beginCaptures: + '1': + name: keyword.operator.js + end: "(?=[(;]|$)" + name: new.expr.js + patterns: + - include: "#type" + - include: "#comment" + null-literal: + match: "\\b(null)\\b" + name: constant.language.null.js + numeric-literal: + match: "\\b(?<=[^$])((0(x|X)[0-9a-fA-F]+)|([0-9]+(\\.[0-9]+)?))\\b" + name: constant.numeric.js + object-body: + begin: "\\{" + beginCaptures: + '0': + name: meta.brace.curly.js + end: "\\}" + endCaptures: + '0': + name: meta.brace.curly.js + name: meta.object.body.js + patterns: + - include: "#string" + - include: "#comment" + - include: "#field-declaration" + - include: "#method-declaration" + - include: "#indexer-declaration" + - include: "#type-annotation" + - include: "#variable-initializer" + - include: "#access-modifier" + - include: "#static-modifier" + - include: "#property-accessor" + object-declaration: + begin: "\\b(?:(export)\\s+)?\\b(?:(abstract)\\s+)?\\b(?=|<>|<|>" + name: keyword.operator.comparison.js + return-type: + begin: "(?<=\\))\\s*:" + end: "(?=$)|(?=\\{|;|//)" + name: meta.return.type.js + patterns: + - include: "#type" + static-modifier: + match: "\\b(static)\\b" + name: keyword.other.js + storage-keyword: + match: "\\b(number|boolean|string|any|var|let|function|const|module|namespace)\\b" + name: storage.type.js + string: + name: string.js + patterns: + - include: "#qstring-single" + - include: "#qstring-double" + string-character-escape: + match: "\\\\(x\\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.|$)" + name: constant.character.escape + switch-block: + begin: "{" + end: "(?=\\})" + name: switch-block.expr.js + patterns: + - include: "#expression" + switch-expression: + begin: "\\b(switch)\\b\\s*\\(" + beginCaptures: + '1': + name: keyword.operator.js + end: "\\)" + name: switch-expression.expr.js + patterns: + - include: "#expression" + switch-statement: + begin: "(?=\\bswitch\\b\\s*\\()" + end: "}" + name: switch-statement.expr.js + patterns: + - include: "#switch-expression" + - include: "#switch-block" + template: + begin: "`" + beginCaptures: + '0': + name: string.template.js + end: "`" + endCaptures: + '0': + name: string.template.js + name: meta.template.js + patterns: + - include: "#template-substitution-element" + - include: "#template-string-contents" + template-string-contents: + begin: ".*?" + end: "(?=(\\$\\{|`))" + name: string.template.js + patterns: + - include: "#string-character-escape" + template-substitution-element: + begin: "\\$\\{" + beginCaptures: + '0': + name: keyword.operator.js + end: "\\}" + endCaptures: + '0': + name: keyword.operator.js + name: template.element.js + patterns: + - include: "#expression" + this-literal: + match: "\\b(this)\\b" + name: constant.language.this.js + type: + name: meta.type.js + patterns: + - include: "#type-primitive" + - include: "#type-parameters" + - include: "#type-tuple" + - include: "#type-object" + - include: "#type-operator" + - include: "#type-paren-or-function-type-parameters" + - include: "#type-function-return-type" + - include: "#type-name" + type-annotation: + begin: ":" + end: "(?=$|[,);\\}\\]]|//)|(?==[^>])|(?<=[\\}>\\]\\)]|[a-zA-Z_$])\\s*(?=\\{)" + name: meta.type.annotation.js + patterns: + - include: "#type" + - include: "#string" + - include: "#comment" + type-declaration: + begin: "\\b(type)\\b\\s+([a-zA-Z_$][\\w$]*)\\s*=\\s*" + beginCaptures: + '1': + name: keyword.other.js + '2': + name: storage.type.js + end: "(?=$|[,);>]|var|type|function|class|interface)" + name: meta.type.declaration.js + patterns: + - include: "#type" + type-function-return-type: + begin: "=>" + beginCaptures: + '0': + name: keyword.operator.js + end: "(?=\\s*[,\\)\\{=;>]|//|$)" + name: meta.type.function.return.js + patterns: + - include: "#type" + type-name: + captures: + '1': + name: entity.name.type.js + match: "[a-zA-Z_$][.\\w$]*" + name: meta.type.name.js + type-object: + begin: "\\{" + beginCaptures: + '0': + name: meta.brace.curly.js + end: "\\}" + endCaptures: + '0': + name: meta.brace.curly.js + name: meta.object.type.js + patterns: + - include: "#comment" + - include: "#field-declaration" + - include: "#method-declaration" + - include: "#indexer-declaration" + - include: "#type-annotation" + type-operator: + match: "[.|]" + name: keyword.operator.type.js + type-parameters: + begin: "([a-zA-Z_$][\\w$]*)?(<)" + beginCaptures: + '1': + name: entity.name.type.js + '2': + name: meta.brace.angle.js + end: "(?=$)|(>)" + endCaptures: + '2': + name: meta.brace.angle.js + name: meta.type.parameters.js + patterns: + - match: "\\b(extends)\\b" + name: keyword.other.js + - include: "#comment" + - include: "#type" + type-paren-or-function-type-parameters: + begin: "(?:\\b(new)\\b)?\\s*\\(" + beginCaptures: + '1': + name: keyword.control.js + end: "\\)" + name: meta.type.paren.cover.js + patterns: + - include: "#comment" + - include: "#type" + - include: "#function-type-parameters" + type-primitive: + captures: + '1': + name: storage.type.js + match: "\\b(string|number|boolean|symbol|any|void)\\b" + name: meta.type.primitive.js + type-tuple: + begin: "\\[" + beginCaptures: + '0': + name: meta.brace.square.js + end: "\\]" + endCaptures: + '0': + name: meta.brace.square.js + name: meta.type.tuple.js + patterns: + - include: "#type" + - include: "#comment" + undefined-literal: + match: "\\b(undefined)\\b" + name: constant.language.js + var-expr: + begin: "(? - - - - fileTypes - - md - mdown - markdown - markdn - - keyEquivalent - ^~M - name - Markdown - patterns - - - include - #block - - - repository - - block - - patterns - - - include - #separator - - - include - #heading - - - include - #blockquote - - - include - #lists - - - include - #raw_block - - - include - #link-def - - - include - #html - - - include - #paragraph - - - repository - - blockquote - - begin - (^|\G)(>) ? - captures - - 2 - - name - punctuation.definition.quote.markdown - - - name - markup.quote.markdown - patterns - - - include - #block - - - while - (^|\G)(>) ? - - heading - - begin - (?:^|\G)(#{1,6})\s*(?=[\S[^#]]) - captures - - 1 - - name - punctuation.definition.heading.markdown - - - contentName - entity.name.section.markdown - end - \s*(#{1,6})?$\n? - name - markup.heading.${1/(#)(#)?(#)?(#)?(#)?(#)?/${6:?6:${5:?5:${4:?4:${3:?3:${2:?2:1}}}}}/}.markdown - patterns - - - include - #inline - - - - heading-setext - - patterns - - - match - ^(={3,})(?=[ \t]*$\n?) - name - markup.heading.setext.1.markdown - - - match - ^(-{3,})(?=[ \t]*$\n?) - name - markup.heading.setext.2.markdown - - - - html - - patterns - - - begin - (?i)(^|\G)(?=<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del).*</\2\s*>\s*$) - end - $ - patterns - - - include - text.html.basic - - - - - begin - (?i)(^|\G)(?=<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)) - patterns - - - include - text.html.basic - - - while - \G(?!</\2\s*>) - - - - link-def - - captures - - 1 - - name - punctuation.definition.constant.markdown - - 10 - - name - punctuation.definition.string.end.markdown - - 11 - - name - string.other.link.description.title.markdown - - 12 - - name - punctuation.definition.string.begin.markdown - - 13 - - name - punctuation.definition.string.end.markdown - - 2 - - name - constant.other.reference.link.markdown - - 3 - - name - punctuation.definition.constant.markdown - - 4 - - name - punctuation.separator.key-value.markdown - - 5 - - name - punctuation.definition.link.markdown - - 6 - - name - markup.underline.link.markdown - - 7 - - name - punctuation.definition.link.markdown - - 8 - - name - string.other.link.description.title.markdown - - 9 - - name - punctuation.definition.string.begin.markdown - - - match - ^(?x: - \s* # Leading whitespace - (\[)(.+?)(\])(:) # Reference name - [ \t]* # Optional whitespace - (<?)(\S+?)(>?) # The url - [ \t]* # Optional whitespace - (?: - ((\().+?(\))) # Match title in quotes… - | ((").+?(")) # or in parens. - )? # Title is optional - \s* # Optional whitespace - $ - ) - name - meta.link.reference.def.markdown - - list_paragraph - - begin - (^|\G)(?=\S)(?![*+-]\s|[0-9]+\.\s) - name - meta.paragraph.markdown - patterns - - - include - #inline - - - include - text.html.basic - - - include - #heading-setext - - - while - (^|\G)(?!\s*$|#|[ ]{0,3}([-*_][ ]{2,}){3,}[ \t]*$\n?|>|[ ]{0,3}[*+-]|[ ]{0,3}[0-9]+\.) - - lists - - patterns - - - begin - (^|\G)([ ]{0,3})([*+-])([ ]{1,3}|\t) - beginCaptures - - 3 - - name - punctuation.definition.list.markdown - - - comment - Currently does not support un-indented second lines. - name - markup.list.unnumbered.markdown - patterns - - - include - #list_paragraph - - - include - #block - - - while - \G([ ]{4}|\t|$) - - - begin - (^|\G)([ ]{0,3})([0-9]+\.)([ ]{1,3}|\t) - beginCaptures - - 3 - - name - punctuation.definition.list.markdown - - - name - markup.list.numbered.markdown - patterns - - - include - #list_paragraph - - - include - #block - - - while - \G([ ]{4}|\t|$) - - - - paragraph - - begin - (^|\G)(?=\S) - name - meta.paragraph.markdown - patterns - - - include - #inline - - - include - text.html.basic - - - include - #heading-setext - - - while - (^|\G)(?!\s*$|#|[ ]{0,3}([-*_][ ]{2,}){3,}[ \t]*$\n?|\s*\[.+?\]:|>) - - raw_block - - begin - (^|\G)([ ]{4}|\t) - name - markup.raw.block.markdown - while - (^|\G)([ ]{4}|\t) - - separator - - match - (^|\G)[ ]{0,3}([-*_])([ ]{0,2}\2){2,}[ \t]*$\n? - name - meta.separator.markdown - - - - inline - - patterns - - - include - #ampersand - - - include - #bracket - - - include - #bold - - - include - #italic - - - include - #raw - - - include - #escape - - - include - #image-inline - - - include - #image-ref - - - include - #link-email - - - include - #link-inet - - - include - #link-inline - - - include - #link-ref - - - include - #link-ref-literal - - - repository - - ampersand - - comment - - Markdown will convert this for us. We match it so that the - HTML grammar will not mark it up as invalid. - - match - &(?!([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+);) - name - meta.other.valid-ampersand.markdown - - bold - - begin - (?x) - (\*\*|__)(?=\S) # Open - (?= - ( - <[^>]*+> # HTML tags - | (?<raw>`+)([^`]|(?!(?<!`)\k<raw>(?!`))`)*+\k<raw> - # Raw - | \\[\\`*_{}\[\]()#.!+\->]?+ # Escapes - | \[ - ( - (?<square> # Named group - [^\[\]\\] # Match most chars - | \\. # Escaped chars - | \[ \g<square>*+ \] # Nested brackets - )*+ - \] - ( - ( # Reference Link - [ ]? # Optional space - \[[^\]]*+\] # Ref name - ) - | ( # Inline Link - \( # Opening paren - [ \t]*+ # Optional whtiespace - <?(.*?)>? # URL - [ \t]*+ # Optional whtiespace - ( # Optional Title - (?<title>['"]) - (.*?) - \k<title> - )? - \) - ) - ) - ) - | (?!(?<=\S)\1). # Everything besides - # style closer - )++ - (?<=\S)\1 # Close - ) - - captures - - 1 - - name - punctuation.definition.bold.markdown - - - end - (?<=\S)(\1) - name - markup.bold.markdown - patterns - - - applyEndPatternLast - 1 - begin - (?=<[^>]*?>) - end - (?<=>) - patterns - - - include - text.html.basic - - - - - include - #escape - - - include - #ampersand - - - include - #bracket - - - include - #raw - - - include - #italic - - - include - #image-inline - - - include - #link-inline - - - include - #link-inet - - - include - #link-email - - - include - #image-ref - - - include - #link-ref-literal - - - include - #link-ref - - - - bracket - - comment - - Markdown will convert this for us. We match it so that the - HTML grammar will not mark it up as invalid. - - match - <(?![a-z/?\$!]) - name - meta.other.valid-bracket.markdown - - escape - - match - \\[-`*_#+.!(){}\[\]\\>] - name - constant.character.escape.markdown - - image-inline - - captures - - 1 - - name - punctuation.definition.string.begin.markdown - - 10 - - name - string.other.link.description.title.markdown - - 11 - - name - punctuation.definition.string.markdown - - 12 - - name - punctuation.definition.string.markdown - - 13 - - name - string.other.link.description.title.markdown - - 14 - - name - punctuation.definition.string.markdown - - 15 - - name - punctuation.definition.string.markdown - - 16 - - name - punctuation.definition.metadata.markdown - - 2 - - name - string.other.link.description.markdown - - 4 - - name - punctuation.definition.string.end.markdown - - 5 - - name - invalid.illegal.whitespace.markdown - - 6 - - name - punctuation.definition.metadata.markdown - - 7 - - name - punctuation.definition.link.markdown - - 8 - - name - markup.underline.link.image.markdown - - 9 - - name - punctuation.definition.link.markdown - - - match - (?x: - \! # Images start with ! - (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\]) - # Match the link text. - ([ ])? # Space not allowed - (\() # Opening paren for url - (<?)(\S+?)(>?) # The url - [ \t]* # Optional whitespace - (?: - ((\().+?(\))) # Match title in parens… - | ((").+?(")) # or in quotes. - )? # Title is optional - \s* # Optional whitespace - (\)) - ) - name - meta.image.inline.markdown - - image-ref - - captures - - 1 - - name - punctuation.definition.string.begin.markdown - - 2 - - name - string.other.link.description.markdown - - 4 - - name - punctuation.definition.string.begin.markdown - - 5 - - name - punctuation.definition.constant.markdown - - 6 - - name - constant.other.reference.link.markdown - - 7 - - name - punctuation.definition.constant.markdown - - - match - \!(\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)(.*?)(\]) - name - meta.image.reference.markdown - - italic - - begin - (?x) - (\*|_)(?=\S) # Open - (?= - ( - <[^>]*+> # HTML tags - | (?<raw>`+)([^`]|(?!(?<!`)\k<raw>(?!`))`)*+\k<raw> - # Raw - | \\[\\`*_{}\[\]()#.!+\->]?+ # Escapes - | \[ - ( - (?<square> # Named group - [^\[\]\\] # Match most chars - | \\. # Escaped chars - | \[ \g<square>*+ \] # Nested brackets - )*+ - \] - ( - ( # Reference Link - [ ]? # Optional space - \[[^\]]*+\] # Ref name - ) - | ( # Inline Link - \( # Opening paren - [ \t]*+ # Optional whtiespace - <?(.*?)>? # URL - [ \t]*+ # Optional whtiespace - ( # Optional Title - (?<title>['"]) - (.*?) - \k<title> - )? - \) - ) - ) - ) - | \1\1 # Must be bold closer - | (?!(?<=\S)\1). # Everything besides - # style closer - )++ - (?<=\S)\1 # Close - ) - - captures - - 1 - - name - punctuation.definition.italic.markdown - - - end - (?<=\S)(\1)((?!\1)|(?=\1\1)) - name - markup.italic.markdown - patterns - - - applyEndPatternLast - 1 - begin - (?=<[^>]*?>) - end - (?<=>) - patterns - - - include - text.html.basic - - - - - include - #escape - - - include - #ampersand - - - include - #bracket - - - include - #raw - - - include - #bold - - - include - #image-inline - - - include - #link-inline - - - include - #link-inet - - - include - #link-email - - - include - #image-ref - - - include - #link-ref-literal - - - include - #link-ref - - - - link-email - - captures - - 1 - - name - punctuation.definition.link.markdown - - 2 - - name - markup.underline.link.markdown - - 4 - - name - punctuation.definition.link.markdown - - - match - (<)((?:mailto:)?[-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(>) - name - meta.link.email.lt-gt.markdown - - link-inet - - captures - - 1 - - name - punctuation.definition.link.markdown - - 2 - - name - markup.underline.link.markdown - - 3 - - name - punctuation.definition.link.markdown - - - match - (<)((?:https?|ftp)://.*?)(>) - name - meta.link.inet.markdown - - link-inline - - captures - - 1 - - name - punctuation.definition.string.begin.markdown - - 10 - - name - string.other.link.description.title.markdown - - 11 - - name - punctuation.definition.string.begin.markdown - - 12 - - name - punctuation.definition.string.end.markdown - - 13 - - name - string.other.link.description.title.markdown - - 14 - - name - punctuation.definition.string.begin.markdown - - 15 - - name - punctuation.definition.string.end.markdown - - 16 - - name - punctuation.definition.metadata.markdown - - 2 - - name - string.other.link.title.markdown - - 4 - - name - punctuation.definition.string.end.markdown - - 5 - - name - invalid.illegal.whitespace.markdown - - 6 - - name - punctuation.definition.metadata.markdown - - 7 - - name - punctuation.definition.link.markdown - - 8 - - name - markup.underline.link.markdown - - 9 - - name - punctuation.definition.link.markdown - - - match - (?x: - (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\]) - # Match the link text. - ([ ])? # Space not allowed - (\() # Opening paren for url - (<?)(.*?)(>?) # The url - [ \t]* # Optional whitespace - (?: - ((\().+?(\))) # Match title in parens… - | ((").+?(")) # or in quotes. - )? # Title is optional - \s* # Optional whitespace - (\)) - ) - name - meta.link.inline.markdown - - link-ref - - captures - - 1 - - name - punctuation.definition.string.begin.markdown - - 2 - - name - string.other.link.title.markdown - - 4 - - name - punctuation.definition.string.end.markdown - - 5 - - name - punctuation.definition.constant.begin.markdown - - 6 - - name - constant.other.reference.link.markdown - - 7 - - name - punctuation.definition.constant.end.markdown - - - match - (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)([^\]]*+)(\]) - name - meta.link.reference.markdown - - link-ref-literal - - captures - - 1 - - name - punctuation.definition.string.begin.markdown - - 2 - - name - string.other.link.title.markdown - - 4 - - name - punctuation.definition.string.end.markdown - - 5 - - name - punctuation.definition.constant.begin.markdown - - 6 - - name - punctuation.definition.constant.end.markdown - - - match - (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)(\]) - name - meta.link.reference.literal.markdown - - raw - - captures - - 1 - - name - punctuation.definition.raw.markdown - - 2 - - 3 - - name - punctuation.definition.raw.markdown - - - match - (`+)([^`]|(?!(?<!`)\1(?!`))`)*+(\1) - name - markup.raw.inline.markdown - - - - - scopeName - text.html.markdown - uuid - 0A1D9874-B448-11D9-BD50-000D93B6E43C - + + + + + fileTypes + + md + mdown + markdown + markdn + + keyEquivalent + ^~M + name + Markdown + patterns + + + include + #block + + + repository + + block + + patterns + + + include + #separator + + + include + #heading + + + include + #blockquote + + + include + #lists + + + include + #raw_block + + + include + #link-def + + + include + #html + + + include + #paragraph + + + repository + + blockquote + + begin + (^|\G)(>) ? + captures + + 2 + + name + punctuation.definition.quote.markdown + + + name + markup.quote.markdown + patterns + + + include + #block + + + while + (^|\G)(>) ? + + heading + + begin + (?:^|\G)(#{1,6})\s*(?=[\S[^#]]) + captures + + 1 + + name + punctuation.definition.heading.markdown + + + contentName + entity.name.section.markdown + end + \s*(#{1,6})?$\n? + name + markup.heading.${1/(#)(#)?(#)?(#)?(#)?(#)?/${6:?6:${5:?5:${4:?4:${3:?3:${2:?2:1}}}}}/}.markdown + patterns + + + include + #inline + + + + heading-setext + + patterns + + + match + ^(={3,})(?=[ \t]*$\n?) + name + markup.heading.setext.1.markdown + + + match + ^(-{3,})(?=[ \t]*$\n?) + name + markup.heading.setext.2.markdown + + + + html + + patterns + + + begin + (?i)(^|\G)(?=<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del).*</\2\s*>\s*$) + end + $ + patterns + + + include + text.html.basic + + + + + begin + (?i)(^|\G)(?=<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)) + patterns + + + include + text.html.basic + + + while + \G(?!</\2\s*>) + + + + link-def + + captures + + 1 + + name + punctuation.definition.constant.markdown + + 10 + + name + punctuation.definition.string.end.markdown + + 11 + + name + string.other.link.description.title.markdown + + 12 + + name + punctuation.definition.string.begin.markdown + + 13 + + name + punctuation.definition.string.end.markdown + + 2 + + name + constant.other.reference.link.markdown + + 3 + + name + punctuation.definition.constant.markdown + + 4 + + name + punctuation.separator.key-value.markdown + + 5 + + name + punctuation.definition.link.markdown + + 6 + + name + markup.underline.link.markdown + + 7 + + name + punctuation.definition.link.markdown + + 8 + + name + string.other.link.description.title.markdown + + 9 + + name + punctuation.definition.string.begin.markdown + + + match + ^(?x: + \s* # Leading whitespace + (\[)(.+?)(\])(:) # Reference name + [ \t]* # Optional whitespace + (<?)(\S+?)(>?) # The url + [ \t]* # Optional whitespace + (?: + ((\().+?(\))) # Match title in quotes… + | ((").+?(")) # or in parens. + )? # Title is optional + \s* # Optional whitespace + $ + ) + name + meta.link.reference.def.markdown + + list_paragraph + + begin + (^|\G)(?=\S)(?![*+-]\s|[0-9]+\.\s) + name + meta.paragraph.markdown + patterns + + + include + #inline + + + include + text.html.basic + + + include + #heading-setext + + + while + (^|\G)(?!\s*$|#|[ ]{0,3}([-*_][ ]{2,}){3,}[ \t]*$\n?|>|[ ]{0,3}[*+-]|[ ]{0,3}[0-9]+\.) + + lists + + patterns + + + begin + (^|\G)([ ]{0,3})([*+-])([ ]{1,3}|\t) + beginCaptures + + 3 + + name + punctuation.definition.list.markdown + + + comment + Currently does not support un-indented second lines. + name + markup.list.unnumbered.markdown + patterns + + + include + #list_paragraph + + + include + #block + + + while + \G([ ]{4}|\t|$) + + + begin + (^|\G)([ ]{0,3})([0-9]+\.)([ ]{1,3}|\t) + beginCaptures + + 3 + + name + punctuation.definition.list.markdown + + + name + markup.list.numbered.markdown + patterns + + + include + #list_paragraph + + + include + #block + + + while + \G([ ]{4}|\t|$) + + + + paragraph + + begin + (^|\G)(?=\S) + name + meta.paragraph.markdown + patterns + + + include + #inline + + + include + text.html.basic + + + include + #heading-setext + + + while + (^|\G)(?!\s*$|#|[ ]{0,3}([-*_][ ]{2,}){3,}[ \t]*$\n?|\s*\[.+?\]:|>) + + raw_block + + begin + (^|\G)([ ]{4}|\t) + name + markup.raw.block.markdown + while + (^|\G)([ ]{4}|\t) + + separator + + match + (^|\G)[ ]{0,3}([-*_])([ ]{0,2}\2){2,}[ \t]*$\n? + name + meta.separator.markdown + + + + inline + + patterns + + + include + #ampersand + + + include + #bracket + + + include + #bold + + + include + #italic + + + include + #raw + + + include + #escape + + + include + #image-inline + + + include + #image-ref + + + include + #link-email + + + include + #link-inet + + + include + #link-inline + + + include + #link-ref + + + include + #link-ref-literal + + + repository + + ampersand + + comment + + Markdown will convert this for us. We match it so that the + HTML grammar will not mark it up as invalid. + + match + &(?!([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+);) + name + meta.other.valid-ampersand.markdown + + bold + + begin + (?x) + (\*\*|__)(?=\S) # Open + (?= + ( + <[^>]*+> # HTML tags + | (?<raw>`+)([^`]|(?!(?<!`)\k<raw>(?!`))`)*+\k<raw> + # Raw + | \\[\\`*_{}\[\]()#.!+\->]?+ # Escapes + | \[ + ( + (?<square> # Named group + [^\[\]\\] # Match most chars + | \\. # Escaped chars + | \[ \g<square>*+ \] # Nested brackets + )*+ + \] + ( + ( # Reference Link + [ ]? # Optional space + \[[^\]]*+\] # Ref name + ) + | ( # Inline Link + \( # Opening paren + [ \t]*+ # Optional whtiespace + <?(.*?)>? # URL + [ \t]*+ # Optional whtiespace + ( # Optional Title + (?<title>['"]) + (.*?) + \k<title> + )? + \) + ) + ) + ) + | (?!(?<=\S)\1). # Everything besides + # style closer + )++ + (?<=\S)\1 # Close + ) + + captures + + 1 + + name + punctuation.definition.bold.markdown + + + end + (?<=\S)(\1) + name + markup.bold.markdown + patterns + + + applyEndPatternLast + 1 + begin + (?=<[^>]*?>) + end + (?<=>) + patterns + + + include + text.html.basic + + + + + include + #escape + + + include + #ampersand + + + include + #bracket + + + include + #raw + + + include + #italic + + + include + #image-inline + + + include + #link-inline + + + include + #link-inet + + + include + #link-email + + + include + #image-ref + + + include + #link-ref-literal + + + include + #link-ref + + + + bracket + + comment + + Markdown will convert this for us. We match it so that the + HTML grammar will not mark it up as invalid. + + match + <(?![a-z/?\$!]) + name + meta.other.valid-bracket.markdown + + escape + + match + \\[-`*_#+.!(){}\[\]\\>] + name + constant.character.escape.markdown + + image-inline + + captures + + 1 + + name + punctuation.definition.string.begin.markdown + + 10 + + name + string.other.link.description.title.markdown + + 11 + + name + punctuation.definition.string.markdown + + 12 + + name + punctuation.definition.string.markdown + + 13 + + name + string.other.link.description.title.markdown + + 14 + + name + punctuation.definition.string.markdown + + 15 + + name + punctuation.definition.string.markdown + + 16 + + name + punctuation.definition.metadata.markdown + + 2 + + name + string.other.link.description.markdown + + 4 + + name + punctuation.definition.string.end.markdown + + 5 + + name + invalid.illegal.whitespace.markdown + + 6 + + name + punctuation.definition.metadata.markdown + + 7 + + name + punctuation.definition.link.markdown + + 8 + + name + markup.underline.link.image.markdown + + 9 + + name + punctuation.definition.link.markdown + + + match + (?x: + \! # Images start with ! + (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\]) + # Match the link text. + ([ ])? # Space not allowed + (\() # Opening paren for url + (<?)(\S+?)(>?) # The url + [ \t]* # Optional whitespace + (?: + ((\().+?(\))) # Match title in parens… + | ((").+?(")) # or in quotes. + )? # Title is optional + \s* # Optional whitespace + (\)) + ) + name + meta.image.inline.markdown + + image-ref + + captures + + 1 + + name + punctuation.definition.string.begin.markdown + + 2 + + name + string.other.link.description.markdown + + 4 + + name + punctuation.definition.string.begin.markdown + + 5 + + name + punctuation.definition.constant.markdown + + 6 + + name + constant.other.reference.link.markdown + + 7 + + name + punctuation.definition.constant.markdown + + + match + \!(\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)(.*?)(\]) + name + meta.image.reference.markdown + + italic + + begin + (?x) + (\*|_)(?=\S) # Open + (?= + ( + <[^>]*+> # HTML tags + | (?<raw>`+)([^`]|(?!(?<!`)\k<raw>(?!`))`)*+\k<raw> + # Raw + | \\[\\`*_{}\[\]()#.!+\->]?+ # Escapes + | \[ + ( + (?<square> # Named group + [^\[\]\\] # Match most chars + | \\. # Escaped chars + | \[ \g<square>*+ \] # Nested brackets + )*+ + \] + ( + ( # Reference Link + [ ]? # Optional space + \[[^\]]*+\] # Ref name + ) + | ( # Inline Link + \( # Opening paren + [ \t]*+ # Optional whtiespace + <?(.*?)>? # URL + [ \t]*+ # Optional whtiespace + ( # Optional Title + (?<title>['"]) + (.*?) + \k<title> + )? + \) + ) + ) + ) + | \1\1 # Must be bold closer + | (?!(?<=\S)\1). # Everything besides + # style closer + )++ + (?<=\S)\1 # Close + ) + + captures + + 1 + + name + punctuation.definition.italic.markdown + + + end + (?<=\S)(\1)((?!\1)|(?=\1\1)) + name + markup.italic.markdown + patterns + + + applyEndPatternLast + 1 + begin + (?=<[^>]*?>) + end + (?<=>) + patterns + + + include + text.html.basic + + + + + include + #escape + + + include + #ampersand + + + include + #bracket + + + include + #raw + + + include + #bold + + + include + #image-inline + + + include + #link-inline + + + include + #link-inet + + + include + #link-email + + + include + #image-ref + + + include + #link-ref-literal + + + include + #link-ref + + + + link-email + + captures + + 1 + + name + punctuation.definition.link.markdown + + 2 + + name + markup.underline.link.markdown + + 4 + + name + punctuation.definition.link.markdown + + + match + (<)((?:mailto:)?[-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(>) + name + meta.link.email.lt-gt.markdown + + link-inet + + captures + + 1 + + name + punctuation.definition.link.markdown + + 2 + + name + markup.underline.link.markdown + + 3 + + name + punctuation.definition.link.markdown + + + match + (<)((?:https?|ftp)://.*?)(>) + name + meta.link.inet.markdown + + link-inline + + captures + + 1 + + name + punctuation.definition.string.begin.markdown + + 10 + + name + string.other.link.description.title.markdown + + 11 + + name + punctuation.definition.string.begin.markdown + + 12 + + name + punctuation.definition.string.end.markdown + + 13 + + name + string.other.link.description.title.markdown + + 14 + + name + punctuation.definition.string.begin.markdown + + 15 + + name + punctuation.definition.string.end.markdown + + 16 + + name + punctuation.definition.metadata.markdown + + 2 + + name + string.other.link.title.markdown + + 4 + + name + punctuation.definition.string.end.markdown + + 5 + + name + invalid.illegal.whitespace.markdown + + 6 + + name + punctuation.definition.metadata.markdown + + 7 + + name + punctuation.definition.link.markdown + + 8 + + name + markup.underline.link.markdown + + 9 + + name + punctuation.definition.link.markdown + + + match + (?x: + (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\]) + # Match the link text. + ([ ])? # Space not allowed + (\() # Opening paren for url + (<?)(.*?)(>?) # The url + [ \t]* # Optional whitespace + (?: + ((\().+?(\))) # Match title in parens… + | ((").+?(")) # or in quotes. + )? # Title is optional + \s* # Optional whitespace + (\)) + ) + name + meta.link.inline.markdown + + link-ref + + captures + + 1 + + name + punctuation.definition.string.begin.markdown + + 2 + + name + string.other.link.title.markdown + + 4 + + name + punctuation.definition.string.end.markdown + + 5 + + name + punctuation.definition.constant.begin.markdown + + 6 + + name + constant.other.reference.link.markdown + + 7 + + name + punctuation.definition.constant.end.markdown + + + match + (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)([^\]]*+)(\]) + name + meta.link.reference.markdown + + link-ref-literal + + captures + + 1 + + name + punctuation.definition.string.begin.markdown + + 2 + + name + string.other.link.title.markdown + + 4 + + name + punctuation.definition.string.end.markdown + + 5 + + name + punctuation.definition.constant.begin.markdown + + 6 + + name + punctuation.definition.constant.end.markdown + + + match + (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)(\]) + name + meta.link.reference.literal.markdown + + raw + + captures + + 1 + + name + punctuation.definition.raw.markdown + + 2 + + 3 + + name + punctuation.definition.raw.markdown + + + match + (`+)([^`]|(?!(?<!`)\1(?!`))`)*+(\1) + name + markup.raw.inline.markdown + + + + + scopeName + text.html.markdown + uuid + 0A1D9874-B448-11D9-BD50-000D93B6E43C + \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/benchmark/GrammarBenchmark.Java.tmLanguage.json b/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/benchmark/GrammarBenchmark.Java.tmLanguage.json new file mode 100644 index 000000000..f0fcef2d0 --- /dev/null +++ b/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/benchmark/GrammarBenchmark.Java.tmLanguage.json @@ -0,0 +1,1030 @@ +{ + "fileTypes": [ + "java", + "bsh" + ], + "keyEquivalent": "^~J", + "name": "Java", + "patterns": [ + { + "captures": { + "1": { + "name": "keyword.other.package.java" + }, + "2": { + "name": "storage.modifier.package.java" + }, + "3": { + "name": "punctuation.terminator.java" + } + }, + "match": "^\\s*(package)\\b(?:\\s*([^ ;$]+)\\s*(;)?)?", + "name": "meta.package.java" + }, + { + "begin": "(import static)\\b\\s*", + "beginCaptures": { + "1": { + "name": "keyword.other.import.static.java" + } + }, + "captures": { + "1": { + "name": "keyword.other.import.java" + }, + "2": { + "name": "storage.modifier.import.java" + }, + "3": { + "name": "punctuation.terminator.java" + } + }, + "contentName": "storage.modifier.import.java", + "end": "\\s*(?:$|(;))", + "endCaptures": { + "1": { + "name": "punctuation.terminator.java" + } + }, + "name": "meta.import.java", + "patterns": [ + { + "match": "\\.", + "name": "punctuation.separator.java" + }, + { + "match": "\\s", + "name": "invalid.illegal.character_not_allowed_here.java" + } + ] + }, + { + "begin": "(import)\\b\\s*", + "beginCaptures": { + "1": { + "name": "keyword.other.import.java" + } + }, + "captures": { + "1": { + "name": "keyword.other.import.java" + }, + "2": { + "name": "storage.modifier.import.java" + }, + "3": { + "name": "punctuation.terminator.java" + } + }, + "contentName": "storage.modifier.import.java", + "end": "\\s*(?:$|(;))", + "endCaptures": { + "1": { + "name": "punctuation.terminator.java" + } + }, + "name": "meta.import.java", + "patterns": [ + { + "match": "\\.", + "name": "punctuation.separator.java" + }, + { + "match": "\\s", + "name": "invalid.illegal.character_not_allowed_here.java" + } + ] + }, + { + "include": "#code" + } + ], + "repository": { + "all-types": { + "patterns": [ + { + "include": "#primitive-arrays" + }, + { + "include": "#primitive-types" + }, + { + "include": "#object-types" + } + ] + }, + "annotations": { + "patterns": [ + { + "begin": "(@[^ (]+)(\\()", + "beginCaptures": { + "1": { + "name": "storage.type.annotation.java" + }, + "2": { + "name": "punctuation.definition.annotation-arguments.begin.java" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.definition.annotation-arguments.end.java" + } + }, + "name": "meta.declaration.annotation.java", + "patterns": [ + { + "captures": { + "1": { + "name": "constant.other.key.java" + }, + "2": { + "name": "keyword.operator.assignment.java" + } + }, + "match": "(\\w*)\\s*(=)" + }, + { + "include": "#code" + }, + { + "match": ",", + "name": "punctuation.separator.property.java" + } + ] + }, + { + "match": "@\\w*", + "name": "storage.type.annotation.java" + } + ] + }, + "anonymous-classes-and-new": { + "begin": "\\bnew\\b", + "beginCaptures": { + "0": { + "name": "keyword.control.new.java" + } + }, + "end": "(?<=\\)|\\])(?!\\s*{)|(?<=})|(?=;)", + "patterns": [ + { + "begin": "(\\w+)\\s*(?=\\[)", + "beginCaptures": { + "1": { + "name": "storage.type.java" + } + }, + "end": "(})|(?=\\s*(?:,|;|\\)))", + "endCaptures": { + "1": { + "name": "punctuation.section.block.end.java" + } + }, + "patterns": [ + { + "begin": "\\[", + "end": "\\]", + "patterns": [ + { + "include": "#code" + } + ] + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.java" + } + }, + "end": "(?=})", + "patterns": [ + { + "include": "#code" + } + ] + } + ] + }, + { + "begin": "(?=\\w.*\\()", + "end": "(?<=\\))", + "patterns": [ + { + "include": "#object-types" + }, + { + "begin": "\\(", + "beginCaptures": { + "1": { + "name": "storage.type.java" + } + }, + "end": "\\)", + "patterns": [ + { + "include": "#code" + } + ] + } + ] + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.inner-class.begin.java" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.section.inner-class.end.java" + } + }, + "name": "meta.inner-class.java", + "patterns": [ + { + "include": "#class-body" + } + ] + } + ] + }, + "assertions": { + "patterns": [ + { + "begin": "\\b(assert)\\s", + "beginCaptures": { + "1": { + "name": "keyword.control.assert.java" + } + }, + "end": "$", + "name": "meta.declaration.assertion.java", + "patterns": [ + { + "match": ":", + "name": "keyword.operator.assert.expression-seperator.java" + }, + { + "include": "#code" + } + ] + } + ] + }, + "class": { + "begin": "(?=\\w?[\\w\\s]*(?:class|(?:@)?interface|enum)\\s+\\w+)", + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.section.class.end.java" + } + }, + "name": "meta.class.java", + "patterns": [ + { + "include": "#storage-modifiers" + }, + { + "include": "#comments" + }, + { + "captures": { + "1": { + "name": "storage.modifier.java" + }, + "2": { + "name": "entity.name.type.class.java" + } + }, + "match": "(class|(?:@)?interface|enum)\\s+(\\w+)", + "name": "meta.class.identifier.java" + }, + { + "begin": "extends", + "beginCaptures": { + "0": { + "name": "storage.modifier.extends.java" + } + }, + "end": "(?={|implements)", + "name": "meta.definition.class.inherited.classes.java", + "patterns": [ + { + "include": "#object-types-inherited" + }, + { + "include": "#comments" + } + ] + }, + { + "begin": "(implements)\\s", + "beginCaptures": { + "1": { + "name": "storage.modifier.implements.java" + } + }, + "end": "(?=\\s*extends|\\{)", + "name": "meta.definition.class.implemented.interfaces.java", + "patterns": [ + { + "include": "#object-types-inherited" + }, + { + "include": "#comments" + } + ] + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.class.begin.java" + } + }, + "end": "(?=})", + "name": "meta.class.body.java", + "patterns": [ + { + "include": "#class-body" + } + ] + } + ] + }, + "class-body": { + "patterns": [ + { + "include": "#comments" + }, + { + "include": "#class" + }, + { + "include": "#enums" + }, + { + "include": "#variables" + }, + { + "include": "#methods" + }, + { + "include": "#annotations" + }, + { + "include": "#storage-modifiers" + }, + { + "include": "#code" + } + ] + }, + "code": { + "patterns": [ + { + "include": "#comments" + }, + { + "include": "#class" + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.block.begin.java" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.section.block.end.java" + } + }, + "patterns": [ + { + "include": "#code" + } + ] + }, + { + "include": "#assertions" + }, + { + "include": "#parens" + }, + { + "include": "#constants-and-special-vars" + }, + { + "include": "#anonymous-classes-and-new" + }, + { + "include": "#annotations" + }, + { + "include": "#keywords" + }, + { + "include": "#storage-modifiers" + }, + { + "include": "#method-call" + }, + { + "include": "#strings" + }, + { + "include": "#all-types" + } + ] + }, + "comments": { + "patterns": [ + { + "captures": { + "0": { + "name": "punctuation.definition.comment.java" + } + }, + "match": "/\\*\\*/", + "name": "comment.block.empty.java" + }, + { + "include": "text.html.javadoc" + }, + { + "include": "#comments-inline" + } + ] + }, + "comments-inline": { + "patterns": [ + { + "begin": "/\\*", + "captures": { + "0": { + "name": "punctuation.definition.comment.java" + } + }, + "end": "\\*/", + "name": "comment.block.java" + }, + { + "begin": "(^[ \\t]+)?(?=//)", + "beginCaptures": { + "1": { + "name": "punctuation.whitespace.comment.leading.java" + } + }, + "end": "(?!\\G)", + "patterns": [ + { + "begin": "//", + "beginCaptures": { + "0": { + "name": "punctuation.definition.comment.java" + } + }, + "end": "\\n", + "name": "comment.line.double-slash.java" + } + ] + } + ] + }, + "constants-and-special-vars": { + "patterns": [ + { + "match": "\\b(true|false|null)\\b", + "name": "constant.language.java" + }, + { + "match": "\\b(this|super)\\b", + "name": "variable.language.java" + }, + { + "match": "\\b0[xX]\\h([\\h_]*\\h)?[lL]?(?!\\w|\\.)", + "name": "constant.numeric.hex.java" + }, + { + "match": "\\b0[0-7_]*[0-7][lL]?\\b", + "name": "constant.numeric.octal.java" + }, + { + "match": "\\b0[bB][01]([01_]*[01])?[lL]?\\b", + "name": "constant.numeric.binary.java" + }, + { + "match": "\\b(0|[1-9]([0-9_]*[0-9])?)[lL]?(?!\\w|\\.)", + "name": "constant.numeric.integer.java" + }, + { + "match": "(?x)\n\t\t\t\t\t\t(?\n\t\t\t\t\t\t\t0[xX]\t\t\t\t\t\t\t\t\t# Start literal\n\t\t\t\t\t\t\t(\\h([\\h_]*\\h)?)?\t\t\t\t\t\t# Optional Number\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t(?<=\\h)\\.\t\t\t\t\t\t\t# A number must exist on\n\t\t\t\t\t\t | \\.(?=\\h)\t\t\t\t\t\t\t# one side of the decimal\n\t\t\t\t\t\t | (?<=\\h)\t\t\t\t\t\t\t\t# Decimal not required\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t(\\h([\\h_]*\\h)?)?\t\t\t\t\t\t# Optional Number\n\t\t\t\t\t\t\t[pP]\t\t\t\t\t\t\t\t\t# Exponent Indicator\n\t\t\t\t\t\t\t[+-]?(0|[1-9]([0-9_]*[0-9])?)\t\t\t# Signed Integer\n\t\t\t\t\t\t\t[fFdD]?\t\t\t\t\t\t\t\t\t# Float Type Suffix\n\t\t\t\t\t\t)\n\t\t\t\t\t\t(?!\\w)\t\t\t\t\t\t\t\t\t\t# Ensure word boundry\n\t\t\t\t\t", + "name": "constant.numeric.hex-float.java" + }, + { + "match": "(?x)\n\t\t\t\t\t\t(?\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t(0|[1-9]([0-9_]*[0-9])?)\t\t\t\t# Leading digits\n\t\t\t\t\t\t\t\t(?=[eEfFdD.])\t\t\t\t\t\t\t# Allow for numbers without .\n\t\t\t\t\t\t\t)?\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t(?<=[0-9])(?=[eEfFdD])\t\t\t\t\t# Allow for numbers without .\n\t\t\t\t\t\t\t | \\.\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t[0-9]([0-9_]*[0-9])?\t\t\t\t\t# Numbers after .\n\t\t\t\t\t\t\t)?\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t[eE][+-]?(0|[1-9]([0-9_]*[0-9])?)\t\t# Exponent\n\t\t\t\t\t\t\t)?\n\t\t\t\t\t\t\t[fFdD]?\t\t\t\t\t\t\t\t\t\t# Float Type Suffix\n\t\t\t\t\t\t)\n\t\t\t\t\t\t(?!\\w)\t\t\t\t\t\t\t\t\t\t\t# Ensure word boundry\n\t\t\t\t\t", + "name": "constant.numeric.float.java" + }, + { + "captures": { + "1": { + "name": "keyword.operator.dereference.java" + } + }, + "match": "(\\.)?\\b([A-Z][A-Z0-9_]+)(?!<|\\.class|\\s*\\w+\\s*=)\\b", + "name": "constant.other.java" + } + ] + }, + "enums": { + "begin": "^(?=\\s*[A-Z0-9_]+\\s*({|\\(|,))", + "end": "(?=;|})", + "patterns": [ + { + "begin": "\\w+", + "beginCaptures": { + "0": { + "name": "constant.other.enum.java" + } + }, + "end": "(?=,|;|})", + "name": "meta.enum.java", + "patterns": [ + { + "include": "#parens" + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.enum.begin.java" + } + }, + "end": "}", + "endCaptures": { + "0": { + "name": "punctuation.section.enum.end.java" + } + }, + "patterns": [ + { + "include": "#class-body" + } + ] + } + ] + }, + { + "include": "#comments" + }, + { + "include": "#annotations" + } + ] + }, + "keywords": { + "patterns": [ + { + "match": "\\b(try|catch|finally|throw)\\b", + "name": "keyword.control.catch-exception.java" + }, + { + "match": "\\?|:", + "name": "keyword.control.ternary.java" + }, + { + "match": "\\b(return|break|case|continue|default|do|while|for|switch|if|else)\\b", + "name": "keyword.control.java" + }, + { + "match": "\\b(instanceof)\\b", + "name": "keyword.operator.java" + }, + { + "match": "(<<|>>>?|~|\\^)", + "name": "keyword.operator.bitwise.java" + }, + { + "match": "((&|\\^|\\||<<|>>>?)=)", + "name": "keyword.operator.assignment.bitwise.java" + }, + { + "match": "(===?|!=|<=|>=|<>|<|>)", + "name": "keyword.operator.comparison.java" + }, + { + "match": "([+*/%-]=)", + "name": "keyword.operator.assignment.arithmetic.java" + }, + { + "match": "(=)", + "name": "keyword.operator.assignment.java" + }, + { + "match": "(\\-\\-|\\+\\+)", + "name": "keyword.operator.increment-decrement.java" + }, + { + "match": "(\\-|\\+|\\*|\\/|%)", + "name": "keyword.operator.arithmetic.java" + }, + { + "match": "(!|&&|\\|\\|)", + "name": "keyword.operator.logical.java" + }, + { + "match": "(\\||&)", + "name": "keyword.operator.bitwise.java" + }, + { + "match": "(?<=\\S)\\.(?=\\S)", + "name": "keyword.operator.dereference.java" + }, + { + "match": ";", + "name": "punctuation.terminator.java" + } + ] + }, + "method-call": { + "begin": "([\\w$]+)(\\()", + "beginCaptures": { + "1": { + "name": "meta.method.java" + }, + "2": { + "name": "punctuation.definition.method-parameters.begin.java" + } + }, + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.method-parameters.end.java" + } + }, + "name": "meta.method-call.java", + "patterns": [ + { + "match": ",", + "name": "punctuation.definition.seperator.parameter.java" + }, + { + "include": "#code" + } + ] + }, + "methods": { + "begin": "(?!new)(?=[\\w<].*\\s+)(?=([^=/]|/(?!/))+\\()", + "end": "(})|(?=;)", + "endCaptures": { + "1": { + "name": "punctuation.section.method.end.java" + } + }, + "name": "meta.method.java", + "patterns": [ + { + "include": "#storage-modifiers" + }, + { + "begin": "(\\w+)\\s*\\(", + "beginCaptures": { + "1": { + "name": "entity.name.function.java" + } + }, + "end": "\\)", + "name": "meta.method.identifier.java", + "patterns": [ + { + "include": "#parameters" + }, + { + "include": "#comments" + } + ] + }, + { + "begin": "<", + "end": ">", + "name": "storage.type.token.java", + "patterns": [ + { + "include": "#object-types" + }, + { + "begin": "<", + "comment": "This is just to support <>'s with no actual type prefix", + "end": ">|[^\\w\\s,\\[\\]<]", + "name": "storage.type.generic.java" + } + ] + }, + { + "begin": "(?=\\w.*\\s+\\w+\\s*\\()", + "end": "(?=\\w+\\s*\\()", + "name": "meta.method.return-type.java", + "patterns": [ + { + "include": "#all-types" + }, + { + "include": "#comments" + } + ] + }, + { + "include": "#throws" + }, + { + "begin": "{", + "beginCaptures": { + "0": { + "name": "punctuation.section.method.begin.java" + } + }, + "end": "(?=})", + "name": "meta.method.body.java", + "patterns": [ + { + "include": "#code" + } + ] + }, + { + "include": "#comments" + } + ] + }, + "object-types": { + "patterns": [ + { + "begin": "\\b((?:[a-z]\\w*\\.)*[A-Z]+\\w*)<", + "end": ">|[^\\w\\s,\\?<\\[\\]]", + "name": "storage.type.generic.java", + "patterns": [ + { + "include": "#object-types" + }, + { + "begin": "<", + "comment": "This is just to support <>'s with no actual type prefix", + "end": ">|[^\\w\\s,\\[\\]<]", + "name": "storage.type.generic.java" + } + ] + }, + { + "begin": "\\b((?:[a-z]\\w*\\.)*[A-Z]+\\w*)(?=\\[)", + "end": "(?=[^\\]\\s])", + "name": "storage.type.object.array.java", + "patterns": [ + { + "begin": "\\[", + "end": "\\]", + "patterns": [ + { + "include": "#code" + } + ] + } + ] + }, + { + "captures": { + "1": { + "name": "keyword.operator.dereference.java" + } + }, + "match": "\\b(?:[a-z]\\w*(\\.))*[A-Z]+\\w*\\b", + "name": "storage.type.java" + } + ] + }, + "object-types-inherited": { + "patterns": [ + { + "begin": "\\b((?:[a-z]\\w*\\.)*[A-Z]+\\w*)<", + "end": ">|[^\\w\\s,<]", + "name": "entity.other.inherited-class.java", + "patterns": [ + { + "include": "#object-types" + }, + { + "begin": "<", + "comment": "This is just to support <>'s with no actual type prefix", + "end": ">|[^\\w\\s,<]", + "name": "storage.type.generic.java" + } + ] + }, + { + "captures": { + "1": { + "name": "keyword.operator.dereference.java" + } + }, + "match": "\\b(?:[a-z]\\w*(\\.))*[A-Z]+\\w*", + "name": "entity.other.inherited-class.java" + } + ] + }, + "parameters": { + "patterns": [ + { + "match": "final", + "name": "storage.modifier.java" + }, + { + "include": "#annotations" + }, + { + "include": "#primitive-arrays" + }, + { + "include": "#primitive-types" + }, + { + "include": "#object-types" + }, + { + "match": "\\w+", + "name": "variable.parameter.java" + } + ] + }, + "parens": { + "begin": "\\(", + "end": "\\)", + "patterns": [ + { + "include": "#code" + } + ] + }, + "primitive-arrays": { + "patterns": [ + { + "match": "\\b(?:void|boolean|byte|char|short|int|float|long|double)(\\[\\])*\\b", + "name": "storage.type.primitive.array.java" + } + ] + }, + "primitive-types": { + "patterns": [ + { + "match": "\\b(?:void|boolean|byte|char|short|int|float|long|double)\\b", + "name": "storage.type.primitive.java" + } + ] + }, + "storage-modifiers": { + "captures": { + "1": { + "name": "storage.modifier.java" + } + }, + "match": "\\b(public|private|protected|static|final|native|synchronized|volatile|abstract|threadsafe|transient)\\b" + }, + "strings": { + "patterns": [ + { + "begin": "\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.java" + } + }, + "end": "\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.java" + } + }, + "name": "string.quoted.double.java", + "patterns": [ + { + "match": "\\\\.", + "name": "constant.character.escape.java" + } + ] + }, + { + "begin": "'", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.java" + } + }, + "end": "'", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.java" + } + }, + "name": "string.quoted.single.java", + "patterns": [ + { + "match": "\\\\.", + "name": "constant.character.escape.java" + } + ] + } + ] + }, + "throws": { + "begin": "throws", + "beginCaptures": { + "0": { + "name": "storage.modifier.java" + } + }, + "end": "(?={|;)", + "name": "meta.throwables.java", + "patterns": [ + { + "include": "#object-types" + } + ] + }, + "values": { + "patterns": [ + { + "include": "#strings" + }, + { + "include": "#object-types" + }, + { + "include": "#constants-and-special-vars" + } + ] + }, + "variables": { + "applyEndPatternLast": 1, + "patterns": [ + { + "begin": "(?x:(?=\n (?:\n (?:private|protected|public|native|synchronized|volatile|abstract|threadsafe|transient|static|final) # visibility/modifier\n |\n (?:def)\n |\n (?:void|boolean|byte|char|short|int|float|long|double)\n |\n (?:(?:[a-z]\\w*\\.)*[A-Z]+\\w*) # object type\n )\n \\s+\n (?!private|protected|public|native|synchronized|volatile|abstract|threadsafe|transient|static|final|def|void|boolean|byte|char|short|int|float|long|double)\n [\\w\\d_<>\\[\\],\\?][\\w\\d_<>\\[\\],\\? \\t]*\n (?:=|$)\n \n\t\t\t\t\t))", + "end": "(?=;)", + "name": "meta.definition.variable.java", + "patterns": [ + { + "match": "\\s" + }, + { + "captures": { + "1": { + "name": "constant.other.variable.java" + } + }, + "match": "([A-Z_0-9]+)\\s+(?=\\=)" + }, + { + "captures": { + "1": { + "name": "meta.definition.variable.name.java" + } + }, + "match": "(\\w[^\\s,]*)\\s+(?=\\=)" + }, + { + "begin": "=", + "beginCaptures": { + "0": { + "name": "keyword.operator.assignment.java" + } + }, + "end": "(?=;)", + "patterns": [ + { + "include": "#code" + } + ] + }, + { + "captures": { + "1": { + "name": "meta.definition.variable.name.java" + } + }, + "match": "(\\w[^\\s=]*)(?=\\s*;)" + }, + { + "include": "#code" + } + ] + } + ] + } + }, + "scopeName": "source.java", + "uuid": "2B449DF6-6B1D-11D9-94EC-000D93589AF6", + "version": "https://github.com/textmate/java.tmbundle/commit/faffa518d0b22b68b4e5e6b4c939722522b97d40" +} \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/benchmark/GrammarBenchmark.JavaFile.txt b/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/benchmark/GrammarBenchmark.JavaFile.txt new file mode 100644 index 000000000..53c05b399 --- /dev/null +++ b/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/benchmark/GrammarBenchmark.JavaFile.txt @@ -0,0 +1,901 @@ +/** + * Copyright (c) 2015-2022 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + * Pierre-Yves B. - Issue #220 Switch to theme only works once for open editor + * IBM Corporation Gerald Mitchell - bug fix + */ +package org.eclipse.tm4e.ui.text; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; +import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.CursorLinePainter; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IPainter; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextInputListener; +import org.eclipse.jface.text.ITextListener; +import org.eclipse.jface.text.ITextOperationTarget; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.ITextViewerExtension5; +import org.eclipse.jface.text.PaintManager; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.TextEvent; +import org.eclipse.jface.text.TextPresentation; +import org.eclipse.jface.text.TextViewer; +import org.eclipse.jface.text.presentation.IPresentationDamager; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.presentation.IPresentationRepairer; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyleRange; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.widgets.Control; +import org.eclipse.tm4e.core.TMException; +import org.eclipse.tm4e.core.grammar.IGrammar; +import org.eclipse.tm4e.core.model.IModelTokensChangedListener; +import org.eclipse.tm4e.core.model.ITMModel; +import org.eclipse.tm4e.core.model.ModelTokensChangedEvent; +import org.eclipse.tm4e.core.model.Range; +import org.eclipse.tm4e.core.model.TMToken; +import org.eclipse.tm4e.registry.TMEclipseRegistryPlugin; +import org.eclipse.tm4e.ui.TMUIPlugin; +import org.eclipse.tm4e.ui.internal.model.TMDocumentModel; +import org.eclipse.tm4e.ui.internal.preferences.PreferenceConstants; +import org.eclipse.tm4e.ui.internal.text.TMPresentationReconcilerTestGenerator; +import org.eclipse.tm4e.ui.internal.themes.ThemeManager; +import org.eclipse.tm4e.ui.internal.utils.ClassHelper; +import org.eclipse.tm4e.ui.internal.utils.ContentTypeHelper; +import org.eclipse.tm4e.ui.internal.utils.ContentTypeInfo; +import org.eclipse.tm4e.ui.internal.utils.PreferenceUtils; +import org.eclipse.tm4e.ui.model.ITMModelManager; +import org.eclipse.tm4e.ui.themes.ITheme; +import org.eclipse.tm4e.ui.themes.IThemeManager; +import org.eclipse.tm4e.ui.themes.ITokenProvider; +import org.eclipse.ui.IEditorPart; + +/** + * TextMate presentation reconciler which must be initialized with: + * + *
      + *
    • a TextMate grammar {@link IGrammar} used to initialize the TextMate model {@link TMDocumentModel}.
    • + *
    • a token provider {@link ITokenProvider} to retrieve the {@link IToken} from a TextMate token type .
    • + *
    + */ +public class TMPresentationReconciler implements IPresentationReconciler { + + /** + * The default text attribute if non is returned as data by the current token + */ + private final Token defaultToken; + + /** The target viewer. */ + @Nullable + private ITextViewer viewer; + + /** The internal listener. */ + private final InternalListener internalListener; + + @Nullable + private IGrammar grammar; + private boolean forcedGrammar; + + @Nullable + private ITokenProvider tokenProvider; + + private final TextAttribute fDefaultTextAttribute; + + @Nullable + private IPreferenceChangeListener themeChangeListener; + + private final List listeners = new ArrayList<>(); + + private boolean initializeViewerColors; + + private boolean updateTextDecorations; + + /** + * true if the presentation reconciler is enabled (grammar and theme are available) and false otherwise. + */ + private boolean enabled; + + /** + * true if a {@link TMException} should be thrown if grammar or theme cannot be found and false otherwise. + */ + private boolean throwError; + + public TMPresentationReconciler() { + this.defaultToken = new Token(null); + this.internalListener = new InternalListener(); + this.fDefaultTextAttribute = new TextAttribute(null); + if (TMEclipseRegistryPlugin.isDebugOptionEnabled("org.eclipse.tm4e.ui/debug/log/GenerateTest")) { + addTMPresentationReconcilerListener(new TMPresentationReconcilerTestGenerator()); + } + setThrowError(TMEclipseRegistryPlugin.isDebugOptionEnabled("org.eclipse.tm4e.ui/debug/log/ThrowError")); + } + + /** + * Listener to recolorize editors when E4 Theme from General / Appearance + * preferences changed or TextMate theme changed.. + */ + private final class ThemeChangeListener implements IPreferenceChangeListener { + + @Override + public void preferenceChange(@Nullable final PreferenceChangeEvent event) { + if(event == null) + return; + final IThemeManager themeManager = TMUIPlugin.getThemeManager(); + switch (event.getKey()) { + case PreferenceConstants.E4_THEME_ID: + preferenceThemeChange((String) event.getNewValue(), themeManager); + break; + case PreferenceConstants.THEME_ASSOCIATIONS: + preferenceThemeChange(PreferenceUtils.getE4PreferenceCSSThemeId(), themeManager); + break; + } + } + + void preferenceThemeChange(@Nullable final String eclipseThemeId, final IThemeManager themeManager) { + final var viewer = TMPresentationReconciler.this.viewer; + if (viewer == null) { + return; + } + + final IDocument document = viewer.getDocument(); + if (document == null) { + return; + } + + final var grammar = TMPresentationReconciler.this.grammar; + if (grammar == null) { + return; + } + // Select the well TextMate theme from the given E4 theme id. + final boolean dark = themeManager.isDarkEclipseTheme(eclipseThemeId); + final ITokenProvider newTheme = themeManager.getThemeForScope(grammar.getScopeName(), dark); + setTheme(newTheme); + } + } + + /** + * Internal listener class. + */ + private final class InternalListener implements ITextInputListener, IModelTokensChangedListener, ITextListener { + + void fireInstall(final ITextViewer viewer, final IDocument document) { + synchronized (listeners) { + for (final ITMPresentationReconcilerListener listener : listeners) { + listener.install(viewer, document); + } + } + } + + void fireUninstall() { + synchronized (listeners) { + for (final ITMPresentationReconcilerListener listener : listeners) { + listener.uninstall(); + } + } + } + + @Override + public void inputDocumentAboutToBeChanged(@Nullable final IDocument oldDocument, + @Nullable final IDocument newDocument) { + if (oldDocument == null) + return; + + final var viewer = TMPresentationReconciler.this.viewer; + if (viewer != null) { + viewer.removeTextListener(this); + } + getTMModelManager().disconnect(oldDocument); + fireUninstall(); + } + + @Override + public void inputDocumentChanged(@Nullable final IDocument oldDocument, @Nullable final IDocument newDocument) { + if (newDocument == null) { + return; + } + + final var viewer = TMPresentationReconciler.this.viewer; + if (viewer == null) + return; + + fireInstall(viewer, newDocument); + try { + viewer.addTextListener(this); + // Update the grammar + final IGrammar localGrammar = findGrammar(newDocument); + + if (localGrammar != null) { + TMPresentationReconciler.this.grammar = localGrammar; + } else if (isThrowError()) { + throw new TMException("Cannot find TextMate grammar for the given document"); + } + + // Update the theme + if (localGrammar != null) { + final String scopeName = localGrammar.getScopeName(); + if (tokenProvider == null) { + tokenProvider = TMUIPlugin.getThemeManager().getThemeForScope(scopeName, + viewer.getTextWidget().getBackground().getRGB()); + } + if (tokenProvider != null) { + applyThemeEditor(); + } else if (isThrowError()) { + throw new TMException("Cannot find Theme for the given grammar '" + scopeName + "'"); + } + } + + if (localGrammar != null) { + final var enable = TMPresentationReconciler.this.enabled = tokenProvider != null; + if (enable) { + // Connect a TextModel to the new document. + final ITMModel model = getTMModelManager().connect(newDocument); + model.setGrammar(localGrammar); + + // Add model listener + model.addModelTokensChangedListener(this); + } + } else { + TMPresentationReconciler.this.enabled = false; + } + } catch (final CoreException e) { + Platform.getLog(Platform.getBundle(TMEclipseRegistryPlugin.PLUGIN_ID)).log( + new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, "Error while initializing TextMate model.", e)); + } + } + + /** + * Finds a grammar for the given document. + * + * @throws CoreException + */ + @Nullable + IGrammar findGrammar(final IDocument newDocument) throws CoreException { + final IGrammar localGrammar = forcedGrammar ? TMPresentationReconciler.this.grammar : null; + if (localGrammar != null) { + return localGrammar; + } + final ContentTypeInfo info = ContentTypeHelper.findContentTypes(newDocument); + if (info == null) { + return null; + } + return findGrammar(info); + } + + @Override + public void textChanged(final @Nullable TextEvent e) { + if (e == null || !e.getViewerRedrawState()) { + return; + } + + final var viewer = TMPresentationReconciler.this.viewer; + if (viewer == null) + return; + + // changed text: propagate previous style, which will be overridden later asynchronously by TM + if (e.getDocumentEvent() != null) { + final int diff = e.getText().length() - e.getLength(); + if (diff == 0 || e.getOffset() <= 0) { + return; + } + final StyleRange range = viewer.getTextWidget().getStyleRangeAtOffset(e.getOffset() - 1); + if (range == null) { + return; + } + range.length = Math.max(0, range.length + diff); + viewer.getTextWidget().setStyleRange(range); + return; + } + + // TextViewer#invalidateTextPresentation is called (because of validation, folding, etc) + // case 2), do the colorization. + final IDocument document = viewer.getDocument(); + if (document == null) { + return; + } + final IRegion region = computeRegionToRedraw(e, document); + if (enabled) { + // case where there is grammar & theme -> update text presentation with the grammar tokens + final ITMModel model = getTMModelManager().connect(document); + + // It's possible that there are two or more SourceViewers opened for the same document, + // so when one of them is closed the existing TMModel is also "closed" and its TokenizerThread + // is interrupted and terminated. + // In this case, in order to let the others Source Viewers to continue working a new + // TMModel object is to be created for the document, so it should be initialized + // with the existing grammar as well as new ModelTokenListener is to be added + final var grammar = TMPresentationReconciler.this.grammar; + if (grammar != null) { + model.setGrammar(grammar); + model.addModelTokensChangedListener(this); + } + + try { + TMPresentationReconciler.this.colorize(region, (TMDocumentModel) model); + } catch (final BadLocationException e1) { + TMUIPlugin.log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e1.getMessage(), e1)); + } + } else { + // case where there is no grammar & theme -> update text presentation with the + // default styles (ex: to support highlighting with GenericEditor) + final TextPresentation presentation = new TextPresentation(region, 100); + presentation.setDefaultStyleRange( + new StyleRange(region.getOffset(), region.getLength(), null, null)); + applyTextRegionCollection(presentation); + } + } + + IRegion computeRegionToRedraw(final TextEvent e, final IDocument document) { + IRegion region = null; + if (e.getOffset() == 0 && e.getLength() == 0 && e.getText() == null) { + // redraw state change, damage the whole document + region = new Region(0, document.getLength()); + } else { + region = widgetRegion2ModelRegion(e); + } + if (region == null || region.getLength() == 0) { + return new Region(0, 0); + } + return region; + } + + /** + * Translates the given text event into the corresponding range of the viewer's document. + * + * @param e + * the text event + * @return the widget region corresponding the region of the given event or null if none + * + * @since 2.1 + */ + @Nullable + IRegion widgetRegion2ModelRegion(final TextEvent e) { + final String text = e.getText(); + final int length = text == null ? 0 : text.length(); + final var viewer = castNonNull(TMPresentationReconciler.this.viewer); + if (viewer instanceof ITextViewerExtension5) { + final ITextViewerExtension5 extension = (ITextViewerExtension5) viewer; + return extension.widgetRange2ModelRange(new Region(e.getOffset(), length)); + } + final IRegion visible = viewer.getVisibleRegion(); + return new Region(e.getOffset() + visible.getOffset(), length); + } + + @Override + public void modelTokensChanged(final ModelTokensChangedEvent event) { + final var viewer = TMPresentationReconciler.this.viewer; + if (viewer != null) { + final Control control = viewer.getTextWidget(); + if (control != null) { + control.getDisplay().asyncExec(() -> { + colorize(event); + }); + } + } + } + + void colorize(final ModelTokensChangedEvent event) { + final var viewer = TMPresentationReconciler.this.viewer; + if (viewer == null) + return; + + final IDocument document = viewer.getDocument(); + if (document == null) { + return; + } + final ITMModel model = event.model; + if (!(model instanceof TMDocumentModel)) { + return; + } + final TMDocumentModel docModel = (TMDocumentModel) model; + for (final Range range : event.ranges) { + try { + final int length = document.getLineOffset(range.toLineNumber - 1) + + document.getLineLength(range.toLineNumber - 1) + - document.getLineOffset(range.fromLineNumber - 1); + final IRegion region = new Region(document.getLineOffset(range.fromLineNumber - 1), length); + TMPresentationReconciler.this.colorize(region, docModel); + } catch (final BadLocationException ex) { + TMUIPlugin.log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, ex.getMessage(), ex)); + } + } + } + + @Nullable + IGrammar findGrammar(@Nullable final ContentTypeInfo info) { + if (info == null) { + return null; + } + final IContentType[] contentTypes = info.getContentTypes(); + // Discover the well grammar from the contentTypes + IGrammar res = TMEclipseRegistryPlugin.getGrammarRegistryManager().getGrammarFor(contentTypes); + if (res == null) { + // Discover the well grammar from the filetype + final String fileName = info.getFileName(); + if (fileName.indexOf('.') > -1) { + final String fileType = new Path(fileName).getFileExtension(); + res = TMEclipseRegistryPlugin.getGrammarRegistryManager().getGrammarForFileType(fileType); + } + } + return res; + } + } + + public void setGrammar(@Nullable final IGrammar grammar) { + var viewer = this.viewer; + final boolean changed = (viewer != null && ((this.grammar == null) || !Objects.equals(grammar, this.grammar))); + this.grammar = grammar; + this.forcedGrammar = true; + if (changed) { + // Grammar has changed, recreate the TextMate model + viewer = castNonNull(viewer); + final IDocument document = viewer.getDocument(); + if (document == null) { + return; + } + internalListener.inputDocumentAboutToBeChanged(viewer.getDocument(), null); + internalListener.inputDocumentChanged(null, document); + } + } + + @Nullable + public IGrammar getGrammar() { + return grammar; + } + + @Nullable + public ITokenProvider getTokenProvider() { + return tokenProvider; + } + + public void setTheme(final ITokenProvider newTheme) { + final ITokenProvider oldTheme = this.tokenProvider; + if (!Objects.equals(oldTheme, newTheme) && grammar != null) { + this.tokenProvider = newTheme; + applyThemeEditor(); + final var viewer = this.viewer; + if (viewer == null) + return; + final IDocument document = viewer.getDocument(); + final ITMModel model = getTMModelManager().connect(document); + if (!(model instanceof TMDocumentModel)) { + return; + } + final TMDocumentModel docModel = (TMDocumentModel) model; + try { + colorize(new Region(0, document.getLength()), docModel); + } catch (final BadLocationException e) { + TMUIPlugin.log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); + } + } + } + + @Override + public void install(@Nullable ITextViewer viewer) { + viewer = this.viewer = castNonNull(viewer); + viewer.addTextInputListener(internalListener); + + final IDocument document = viewer.getDocument(); + if (document != null) { + internalListener.inputDocumentChanged(null, document); + } + final var themeChangeListener = this.themeChangeListener = new ThemeChangeListener(); + ThemeManager.getInstance().addPreferenceChangeListener(themeChangeListener); + } + + @Override + public void uninstall() { + final var viewer = castNonNull(this.viewer); + viewer.removeTextInputListener(internalListener); + // Ensure we uninstall all listeners + internalListener.inputDocumentAboutToBeChanged(viewer.getDocument(), null); + final var themeChangeListener = this.themeChangeListener; + if (themeChangeListener != null) { + ThemeManager.getInstance().removePreferenceChangeListener(themeChangeListener); + } + this.themeChangeListener = null; + } + + @Nullable + @Override + public IPresentationDamager getDamager(@Nullable final String contentType) { + return null; + } + + @Nullable + @Override + public IPresentationRepairer getRepairer(@Nullable final String contentType) { + return null; + } + + private ITMModelManager getTMModelManager() { + return TMUIPlugin.getTMModelManager(); + } + + void colorize(final IRegion damage, final TMDocumentModel model) throws BadLocationException { + final IDocument document = model.getDocument(); + final int fromLineNumber = document.getLineOfOffset(damage.getOffset()); + final int toLineNumber = document.getLineOfOffset(damage.getOffset() + damage.getLength()); + applyThemeEditorIfNeeded(); + // Refresh the UI Presentation + TMUIPlugin.trace("Render from: " + fromLineNumber + " to: " + toLineNumber); + final var presentation = new TextPresentation(damage, 1000); + Exception error = null; + try { + int lastStart = presentation.getExtent().getOffset(); + int length = 0; + boolean firstToken = true; + IToken lastToken = Token.UNDEFINED; + TextAttribute lastAttribute = getTokenTextAttribute(lastToken); + + List tokens = null; + for (int line = fromLineNumber; line <= toLineNumber; line++) { + tokens = model.getLineTokens(line); + if (tokens == null) { + // TextMate tokens was not computed for this line. + // This case comes from when the viewer is invalidated (by + // validation for instance) and textChanged is called. + // see https://github.com/eclipse/tm4e/issues/78 + TMUIPlugin.trace("TextMate tokens not available for line " + line); + break; + } + final int startLineOffset = document.getLineOffset(line); + for (int i = 0; i < tokens.size(); i++) { + final TMToken currentToken = tokens.get(i); + final TMToken nextToken = (i + 1 < tokens.size()) ? tokens.get(i + 1) : null; + int tokenStartIndex = currentToken.startIndex; + + if (isBeforeRegion(currentToken, startLineOffset, damage)) { + // The token is before the damage region + if (nextToken != null) { + if (isBeforeRegion(nextToken, startLineOffset, damage)) { + continue; // ignore it + } + tokenStartIndex = damage.getOffset() - startLineOffset; + } else { + tokenStartIndex = damage.getOffset() - startLineOffset; + final IToken token = toToken(currentToken); + lastAttribute = getTokenTextAttribute(token); + length += getTokenLengh(tokenStartIndex, nextToken, line, document); + firstToken = false; + // ignore it + continue; + } + } else if (isAfterRegion(currentToken, startLineOffset, damage)) { + // The token is after the damage region, stop the colorization process + break; + } + + final IToken token = toToken(currentToken); + final TextAttribute attribute = getTokenTextAttribute(token); + if (lastAttribute.equals(attribute)) { + length += getTokenLengh(tokenStartIndex, nextToken, line, document); + firstToken = false; + } else { + if (!firstToken) { + addRange(presentation, lastStart, length, lastAttribute); + } + firstToken = false; + lastToken = token; + lastAttribute = attribute; + lastStart = tokenStartIndex + startLineOffset; + length = getTokenLengh(tokenStartIndex, nextToken, line, document); + } + } + } + // adjust the length + length = Math.min(length, damage.getOffset() + damage.getLength() - lastStart); + addRange(presentation, lastStart, length, lastAttribute); + applyTextRegionCollection(presentation); + } catch (final Exception e) { + error = e; + TMUIPlugin.log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); + } finally { + fireColorize(presentation, error); + } + } + + /** + * Return true if the given token is before the given region and false + * otherwise. + * + * @param token + * @param startLineOffset + * @param damage + * + * @return + */ + private boolean isBeforeRegion(final TMToken token, final int startLineOffset, final IRegion damage) { + return token.startIndex + startLineOffset < damage.getOffset(); + } + + /** + * Return true if the given token is after the given region and false otherwise. + * + * @param t + * @param startLineOffset + * @param damage + * + * @return + */ + private boolean isAfterRegion(final TMToken t, final int startLineOffset, final IRegion damage) { + return t.startIndex + startLineOffset >= damage.getOffset() + damage.getLength(); + } + + private IToken toToken(final TMToken t) { + final var tokenProvider = this.tokenProvider; + if (tokenProvider != null) { + final IToken token = tokenProvider.getToken(t.type); + if (token != null) { + return token; + } + } + return defaultToken; + } + + private int getTokenLengh(final int tokenStartIndex, @Nullable final TMToken nextToken, final int line, + final IDocument document) + throws BadLocationException { + if (nextToken != null) { + return nextToken.startIndex - tokenStartIndex; + } + return document.getLineLength(line) - tokenStartIndex; + } + + /** + * Returns a text attribute encoded in the given token. If the token's data is + * not null and a text attribute it is assumed that it is the + * encoded text attribute. It returns the default text attribute if there is no + * encoded text attribute found. + * + * @param token + * the token whose text attribute is to be determined + * + * @return the token's text attribute + */ + protected TextAttribute getTokenTextAttribute(final IToken token) { + final Object data = token.getData(); + if (data instanceof TextAttribute) { + return (TextAttribute) data; + } + return fDefaultTextAttribute; + } + + /** + * Adds style information to the given text presentation. + * + * @param presentation + * the text presentation to be extended + * @param offset + * the offset of the range to be styled + * @param length + * the length of the range to be styled + * @param attr + * the attribute describing the style of the range to be styled + * @param lastLineStyleRanges + */ + protected void addRange(final TextPresentation presentation, final int offset, final int length, + @Nullable final TextAttribute attr) { + if (attr != null) { + final int style = attr.getStyle(); + final int fontStyle = style & (SWT.ITALIC | SWT.BOLD | SWT.NORMAL); + final StyleRange styleRange = new StyleRange(offset, length, attr.getForeground(), attr.getBackground(), + fontStyle); + styleRange.strikeout = (style & TextAttribute.STRIKETHROUGH) != 0; + styleRange.underline = (style & TextAttribute.UNDERLINE) != 0; + styleRange.font = attr.getFont(); + presentation.addStyleRange(styleRange); + } + } + + /** + * Applies the given text presentation to the text viewer the presentation + * reconciler is installed on. + * + * @param presentation + * the text presentation to be applied to the text viewer + */ + private void applyTextRegionCollection(final TextPresentation presentation) { + final var viewer = this.viewer; + if (viewer != null) { + viewer.changeTextPresentation(presentation, false); + } + } + + /** + * Add a TextMate presentation reconciler listener. + * + * @param listener + * the TextMate presentation reconciler listener to add. + */ + public void addTMPresentationReconcilerListener(final ITMPresentationReconcilerListener listener) { + synchronized (listeners) { + if (!listeners.contains(listener)) { + listeners.add(listener); + } + } + } + + /** + * Remove a TextMate presentation reconciler listener. + * + * @param listener + * the TextMate presentation reconciler listener to remove. + */ + public void removeTMPresentationReconcilerListener(final ITMPresentationReconcilerListener listener) { + synchronized (listeners) { + listeners.remove(listener); + } + } + + /** + * Fire colorize. + */ + private void fireColorize(final TextPresentation presentation, @Nullable final Throwable error) { + synchronized (listeners) { + for (final ITMPresentationReconcilerListener listener : listeners) { + listener.colorize(presentation, error); + } + } + } + + @Nullable + public static TMPresentationReconciler getTMPresentationReconciler(@Nullable final IEditorPart editorPart) { + if (editorPart == null) { + return null; + } + @Nullable + final ITextOperationTarget target = editorPart.getAdapter(ITextOperationTarget.class); + if (target instanceof ITextViewer) { + final ITextViewer textViewer = ((ITextViewer) target); + return TMPresentationReconciler.getTMPresentationReconciler(textViewer); + } + return null; + } + + /** + * Returns the {@link TMPresentationReconciler} of the given text viewer and null otherwise. + * + * @return the {@link TMPresentationReconciler} of the given text viewer and null otherwise. + */ + @Nullable + public static TMPresentationReconciler getTMPresentationReconciler(final ITextViewer textViewer) { + try { + final Field field = SourceViewer.class.getDeclaredField("fPresentationReconciler"); + if (field != null) { + field.trySetAccessible(); + final Object presentationReconciler = field.get(textViewer); + // field is IPresentationRecounciler, looking for TMPresentationReconciler implementation + return presentationReconciler instanceof TMPresentationReconciler + ? (TMPresentationReconciler) presentationReconciler + : null; + } + } catch (SecurityException | NoSuchFieldException e) { + // if SourceViewer class no longer has fPresentationReconciler or changes access level + TMUIPlugin.log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); + } catch (IllegalArgumentException | IllegalAccessException | NullPointerException + | ExceptionInInitializerError iae) { + // This should not be logged as an error. This is an expected possible outcome of field.get(textViewer). + // The method assumes ITextViewer is actually ISourceViewer, and specifically the SourceViewer + // implementation + // that was available at the current build. This code also works with any implementation that follows the + // internal structure if also an ITextViewer. + // If these assumptions are false, the method should return null. Logging causes repeat noise. + } + return null; + } + + /** + * Initialize foreground, background color, current line highlight from the current theme. + */ + private void applyThemeEditor() { + this.initializeViewerColors = false; + this.updateTextDecorations = false; + applyThemeEditorIfNeeded(); + } + + /** + * Initialize foreground, background color, current line highlight from the current theme if needed. + */ + private void applyThemeEditorIfNeeded() { + final var viewer = castNonNull(this.viewer); + final var tokenProvider = castNonNull(this.tokenProvider); + + if (!initializeViewerColors) { + final StyledText styledText = viewer.getTextWidget(); + ((ITheme) tokenProvider).initializeViewerColors(styledText); + initializeViewerColors = true; + } + if (updateTextDecorations) { + return; + } + try { + // Ugly code to update "current line highlight" : + // - get the PaintManager from the ITextViewer with reflection. + // - get the list of IPainter of PaintManager with reflection + // - loop for IPainter to retrieve CursorLinePainter which manages "current line + // highlight". + final PaintManager paintManager = ClassHelper.getFieldValue(viewer, "fPaintManager", TextViewer.class); + if (paintManager == null) { + return; + } + final List painters = ClassHelper.getFieldValue(paintManager, "fPainters", PaintManager.class); + if (painters == null) { + return; + } + for (final IPainter painter : painters) { + if (painter instanceof CursorLinePainter) { + // Update current line highlight + final Color background = tokenProvider.getEditorCurrentLineHighlight(); + if (background != null) { + ((CursorLinePainter) painter).setHighlightColor(background); + } + updateTextDecorations = true; + } + } + } catch (final Exception e) { + TMUIPlugin.log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); + } + } + + /** + * Set true if a {@link TMException} should be thrown if grammar or theme cannot + * be found and false otherwise. + * + * @param throwError + */ + public void setThrowError(final boolean throwError) { + this.throwError = throwError; + } + + /** + * Return true if a {@link TMException} should be thrown if grammar or theme + * cannot be found and false otherwise. + * + * @return true if a {@link TMException} should be thrown if grammar or theme + * cannot be found and false otherwise. + */ + public boolean isThrowError() { + return throwError; + } + + /** + * Returns true if the presentation reconciler is enabled (grammar and theme are + * available) and false otherwise. + * + * @return true if the presentation reconciler is enabled (grammar and theme are + * available) and false otherwise. + */ + + public boolean isEnabled() { + return enabled; + } +} diff --git a/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/internal/grammar/parser/json/csharp.json b/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/internal/grammar/parser/json/csharp.json deleted file mode 100644 index 3621982a8..000000000 --- a/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/internal/grammar/parser/json/csharp.json +++ /dev/null @@ -1,641 +0,0 @@ -{ - "scopeName": "source.cs", - "name": "C#", - "fileTypes": [ - "cs" - ], - "foldingStartMarker": "^\\s*#\\s*region|^\\s*/\\*|^(?![^{]*?//|[^{]*?/\\*(?!.*?\\*/.*?\\{)).*?\\{\\s*($|//|/\\*(?!.*?\\*/.*\\S))", - "foldingStopMarker": "^\\s*#\\s*endregion|^\\s*\\*/|^\\s*\\}", - "patterns": [ - { - "include": "#using" - }, - { - "include": "#namespace" - }, - { - "include": "#code" - } - ], - "repository": { - "using": { - "begin": "^\\s*(using)\\b\\s*", - "captures": { - "1": { - "name": "keyword.other.using.cs" - } - }, - "end": "\\s*(?:$|;)" - }, - "namespace": { - "begin": "^\\s*[^@]?((namespace)\\s+([\\w.]+))", - "beginCaptures": { - "1": { - "name": "meta.namespace.identifier.cs" - }, - "2": { - "name": "keyword.other.namespace.cs" - }, - "3": { - "name": "entity.name.type.namespace.cs" - } - }, - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.section.namespace.end.cs" - } - }, - "name": "meta.namespace.cs", - "patterns": [ - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.section.namespace.begin.cs" - } - }, - "end": "(?=})", - "name": "meta.namespace.body.cs", - "patterns": [ - { - "include": "#using" - }, - { - "include": "#namespace" - }, - { - "include": "#code" - } - ] - } - ] - }, - "variable": { - "patterns": [ - { - "match": "\\b(var)\\s+(.*?)(?=(=|;))", - "captures": { - "1": { - "name": "keyword.other.var.cs" - } - } - }, - { - "match": "\\b(?!var|return|yield|throw)([\\w<>*?\\[\\]]+)\\s+([\\w]+)\\s*(?=(=(?!=)|;))", - "captures": { - "1": { - "name": "storage.type.variable.cs" - } - } - } - ] - }, - "block": { - "patterns": [ - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.section.block.begin.cs" - } - }, - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.section.block.end.cs" - } - }, - "name": "meta.block.cs", - "patterns": [ - { - "include": "#code" - } - ] - } - ] - }, - "builtinTypes": { - "patterns": [ - { - "match": "\\b(bool|byte|sbyte|char|decimal|double|float|int|uint|long|ulong|object|short|ushort|string|void|class|struct|enum|interface)\\b", - "name": "storage.type.cs" - } - ] - }, - "class": { - "begin": "(?=\\w?[\\w\\s]*[^@]?(?:class|struct|interface|enum)\\s+\\w+)", - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.section.class.end.cs" - } - }, - "name": "meta.class.cs", - "patterns": [ - { - "include": "#storage-modifiers" - }, - { - "include": "#comments" - }, - { - "captures": { - "1": { - "name": "storage.modifier.cs" - }, - "2": { - "name": "entity.name.type.class.cs" - } - }, - "match": "(class|struct|interface|enum)\\s+(\\w+)", - "name": "meta.class.identifier.cs" - }, - { - "begin": ":", - "end": "(?={)", - "patterns": [ - { - "captures": { - "1": { - "name": "storage.type.cs" - } - }, - "match": "\\s*,?([A-Za-z_]\\w*)\\b" - } - ] - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.section.class.begin.cs" - } - }, - "end": "(?=})", - "name": "meta.class.body.cs", - "patterns": [ - { - "include": "#method" - }, - { - "include": "#code" - } - ] - } - ] - }, - "code": { - "patterns": [ - { - "include": "#block" - }, - { - "include": "#comments" - }, - { - "include": "#class" - }, - { - "include": "#variable" - }, - { - "include": "#constants" - }, - { - "include": "#storage-modifiers" - }, - { - "include": "#keywords" - }, - { - "include": "#preprocessor" - }, - { - "include": "#method-call" - }, - { - "include": "#builtinTypes" - }, - { - "include": "#documentation" - } - ] - }, - "comments": { - "patterns": [ - { - "begin": "///", - "captures": { - "0": { - "name": "punctuation.definition.comment.cs" - } - }, - "end": "$\\n?", - "name": "comment.block.documentation.cs", - "patterns": [ - { - "include": "text.xml" - } - ] - }, - { - "begin": "/\\*", - "captures": { - "0": { - "name": "punctuation.definition.comment.cs" - } - }, - "end": "\\*/\\n?", - "name": "comment.block.cs" - }, - { - "begin": "//", - "captures": { - "1": { - "name": "punctuation.definition.comment.cs" - } - }, - "end": "$\\n?", - "name": "comment.line.double-slash.cs" - } - ] - }, - "constants": { - "patterns": [ - { - "match": "\\b(true|false|null|this|base)\\b", - "name": "constant.language.cs" - }, - { - "match": "\\b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\\.?[0-9]*)|(\\.[0-9]+))((e|E)(\\+|-)?[0-9]+)?)(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b", - "name": "constant.numeric.cs" - }, - { - "captures": { - "0": { - "name": "punctuation.definition.string.begin.cs" - } - }, - "match": "@\"([^\"]|\"\")*\"", - "name": "string.quoted.double.literal.cs" - }, - { - "begin": "\"", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.cs" - } - }, - "end": "\"", - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.cs" - } - }, - "name": "string.quoted.double.cs", - "patterns": [ - { - "match": "\\\\.", - "name": "constant.character.escape.cs" - } - ] - }, - { - "begin": "'", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.cs" - } - }, - "end": "'", - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.cs" - } - }, - "name": "string.quoted.single.cs", - "patterns": [ - { - "match": "\\\\.", - "name": "constant.character.escape.cs" - } - ] - } - ] - }, - "keywords": { - "patterns": [ - { - "match": "\\b(if|else|while|for|foreach|in|do|return|continue|break|switch|case|default|goto|throw|try|catch|finally|lock|yield|await|when)\\b", - "name": "keyword.control.cs" - }, - { - "match": "\\b(from|where|select|group|into|orderby|join|let|on|equals|by|ascending|descending)\\b", - "name": "keyword.linq.cs" - }, - { - "match": "\\b(event|delegate|fixed|add|remove|set|get|value|new|is|as|using|checked|unchecked|typeof|sizeof|stackalloc|nameof)\\b", - "name": "keyword.other.cs" - }, - { - "match": "[@]\\b(namespace|class|var|event|delegate|add|remove|set|get|value|new|is|as|using|checked|unchecked|typeof|sizeof|nameof|when|override|readonly|stackalloc|from|where|select|group|into|orderby|join|let|on|equals|by|ascending|descending|if|else|while|for|foreach|in|do|return|continue|break|switch|case|default|goto|throw|try|catch|finally|lock|yield|await|internal|public|protected|private|static|const|sealed|abstract|virtual|extern|unsafe|volatile|implicit|explicit|operator|async|partial|bool|byte|sbyte|char|decimal|double|float|int|uint|long|ulong|object|short|ushort|string|void|struct|enum|interface)\\b", - "name": "meta.class.body.cs" - } - ] - }, - "method": { - "patterns": [ - { - "begin": "\\[", - "end": "\\]", - "name": "meta.method.annotation.cs", - "patterns": [ - { - "include": "#constants" - }, - { - "include": "#preprocessor" - }, - { - "include": "#builtinTypes" - } - ] - }, - { - "begin": "(?=\\bnew\\s+)(?=[\\w<].*\\s+)(?=[^=]+\\()", - "end": "(?={|;)", - "name": "meta.new-object.cs", - "patterns": [ - { - "include": "#code" - } - ] - }, - { - "begin": "(?\\s,`?]*>)?)\\s*\\(", - "beginCaptures": { - "1": { - "name": "entity.name.function.cs" - } - }, - "end": "\\)", - "name": "meta.method.identifier.cs", - "patterns": [ - { - "include": "#parameters" - }, - { - "include": "#constants" - } - ] - }, - { - "begin": "(?=\\w.*\\s+[\\w.]+\\s*\\()", - "end": "(?=[\\w.]+\\s*\\()", - "name": "meta.method.return-type.cs", - "patterns": [ - { - "include": "#builtinTypes" - } - ] - }, - { - "begin": ":\\s*(this|base)\\s*\\(", - "beginCaptures": { - "1": { - "name": "constant.language.cs" - } - }, - "end": "\\)", - "name": "meta.method.base-call.cs", - "patterns": [ - { - "include": "#builtinTypes" - } - ] - }, - { - "begin": "=>", - "beginCaptures": { - "0": { - "name": "punctuation.section.method.begin.cs" - } - }, - "end": "(?=;)", - "name": "meta.method.body.cs", - "patterns": [ - { - "include": "#code" - } - ] - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.section.method.begin.cs" - } - }, - "end": "(?=})", - "name": "meta.method.body.cs", - "patterns": [ - { - "include": "#code" - } - ] - } - ] - }, - { - "begin": "(?!new)(?=[\\w<].*\\s+)(?=[^\\(]+=>)", - "end": ";", - "endCaptures": { - "0": { - "name": "punctuation.section.property.end.cs" - } - }, - "name": "meta.property.cs", - "patterns": [ - { - "include": "#storage-modifiers" - }, - { - "begin": "(?=([\\w.]+)\\s*=>)", - "captures": { - "1": { - "name": "entity.name.function.cs" - } - }, - "end": "(?==>)", - "name": "meta.method.identifier.cs" - }, - { - "begin": "(?=\\w.*\\s+[\\w.]+\\s*=>)", - "end": "(?=[\\w.]+\\s*=>)", - "name": "meta.method.return-type.cs", - "patterns": [ - { - "include": "#builtinTypes" - } - ] - }, - { - "begin": "=>", - "beginCaptures": { - "0": { - "name": "punctuation.section.property.begin.cs" - } - }, - "end": "(?=;)", - "name": "meta.method.body.cs", - "patterns": [ - { - "include": "#code" - } - ] - } - ] - }, - { - "begin": "(?!new)(?=[\\w<].*\\s+)(?=[^=\\(]+\\{)", - "end": "}", - "endCaptures": { - "0": { - "name": "punctuation.section.property.end.cs" - } - }, - "name": "meta.property.cs", - "patterns": [ - { - "include": "#storage-modifiers" - }, - { - "begin": "([\\w.]+)\\s*(?={)", - "captures": { - "1": { - "name": "entity.name.function.cs" - } - }, - "end": "(?={)", - "name": "meta.method.identifier.cs" - }, - { - "begin": "(?=\\w.*\\s+[\\w.]+\\s*\\{)", - "end": "(?=[\\w.]+\\s*\\{)", - "name": "meta.method.return-type.cs", - "patterns": [ - { - "include": "#builtinTypes" - } - ] - }, - { - "begin": "{", - "beginCaptures": { - "0": { - "name": "punctuation.section.property.begin.cs" - } - }, - "end": "(?=})", - "name": "meta.method.body.cs", - "patterns": [ - { - "include": "#code" - } - ] - } - ] - } - ] - }, - "method-call": { - "begin": "([\\w$]+)\\s*(\\()", - "beginCaptures": { - "1": { - "name": "meta.method.cs" - }, - "2": { - "name": "punctuation.definition.method-parameters.begin.cs" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.definition.method-parameters.end.cs" - } - }, - "name": "meta.method-call.cs", - "patterns": [ - { - "match": ",", - "name": "punctuation.definition.seperator.parameter.cs" - }, - { - "include": "#code" - } - ] - }, - "parameters": { - "begin": "\\b(ref|params|out)?\\s*\\b(\\w+(?:\\s*<.*?>)?(?:\\s*\\*)*(?:\\s*\\?)?(?:\\s*\\[.*?\\])?)\\s+(@?\\w+)\\s*(=)?", - "beginCaptures": { - "1": { - "name": "storage.type.modifier.cs" - }, - "2": { - "name": "storage.type.generic.cs" - }, - "3": { - "name": "variable.parameter.function.cs" - }, - "4": { - "name": "keyword.operator.assignment.cs" - } - }, - "end": "(?:(,)|(?=[\\)]))", - "endCaptures": { - "1": { - "name": "punctuation.definition.separator.parameter.cs" - } - }, - "patterns": [ - { - "include": "#constants" - }, - { - "include": "#block" - } - ] - }, - "preprocessor": { - "patterns": [ - { - "captures": { - "2": { - "name": "entity.name.function.preprocessor.cs" - } - }, - "match": "^\\s*#\\s*(if|else|elif|endif|define|undef|warning|error|line|pragma|region|endregion)\\b\\s*(.*?)(?=$|\\/\\/)", - "name": "meta.preprocessor.cs" - } - ] - }, - "storage-modifiers": { - "match": "\\b(event|delegate|internal|public|protected|private|static|const|new|sealed|abstract|virtual|override|extern|unsafe|readonly|volatile|implicit|explicit|operator|async|partial)\\b", - "name": "storage.modifier.cs" - } - } -} \ No newline at end of file diff --git a/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/internal/grammar/parser/xml/JavaScript.tmLanguage b/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/internal/grammar/parser/xml/JavaScript.tmLanguage deleted file mode 100644 index 389da2c6f..000000000 --- a/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/internal/grammar/parser/xml/JavaScript.tmLanguage +++ /dev/null @@ -1,2205 +0,0 @@ - - - - fileTypes - - js - jsx - - name - JavaScript (with React support) - patterns - - - include - #expression - - - repository - - access-modifier - - match - \b(public|protected|private)\b - name - storage.modifier.js - - arithmetic-operator - - match - \*|/|\-\-|\-|\+\+|\+|% - name - keyword.operator.arithmetic.js - - array-literal - - begin - \[ - beginCaptures - - 0 - - name - meta.brace.square.js - - - end - \] - endCaptures - - 0 - - name - meta.brace.square.js - - - name - meta.array.literal.js - patterns - - - include - #expression - - - - assignment-operator - - match - <<=|>>=|>>>=|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^= - name - keyword.operator.assignment.js - - await-modifier - - match - \bawait\b - name - storage.modifier.js - - block - - begin - \{ - beginCaptures - - 0 - - name - meta.brace.curly.js - - - end - \} - endCaptures - - 0 - - name - meta.brace.curly.js - - - name - meta.block.js - patterns - - - include - #object-member - - - include - #expression - - - - boolean-literal - - match - \b(false|true)\b - name - constant.language.boolean.js - - case-clause - - begin - (?<!\.)\b(case|default)\b - beginCaptures - - 1 - - name - keyword.control.js - - - end - : - name - case-clause.expr.js - patterns - - - include - #expression - - - - comment - - name - comment.js - patterns - - - include - #comment-block-doc - - - include - #comment-block - - - include - #comment-line - - - - comment-block - - begin - /\* - end - \*/ - name - comment.block.js - - comment-block-doc - - begin - /\*\*(?!/) - end - \*/ - name - comment.block.documentation.js - - comment-line - - match - (//).*$\n? - name - comment.line.js - - control-statement - - match - (?<!\.)\b(break|catch|continue|debugger|declare|do|else|finally|for|if|return|switch|throw|try|while|with|super|case|default)\b - name - keyword.control.js - - decl-block - - begin - \{ - beginCaptures - - 0 - - name - meta.brace.curly.js - - - end - \} - endCaptures - - 0 - - name - meta.brace.curly.js - - - name - meta.decl.block.js - patterns - - - include - #expression - - - - declaration - - name - meta.declaration.js - patterns - - - include - #function-declaration - - - include - #object-declaration - - - include - #type-declaration - - - include - #enum-declaration - - - - enum-declaration - - captures - - 1 - - name - storage.modifier.js - - 2 - - name - storage.type.js - - 3 - - name - entity.name.class.js - - - match - (?:\b(const)\s+)?\b(enum)\s+([a-zA-Z_$][\w$]*) - name - meta.enum.declaration.js - - expression - - name - meta.expression.js - patterns - - - include - #jsx - - - include - #for-in-simple - - - include - #string - - - include - #regex - - - include - #template - - - include - #comment - - - include - #literal - - - include - #paren-expression - - - include - #var-expr - - - include - #declaration - - - include - #new-expr - - - include - #switch-statement - - - include - #block - - - include - #expression-operator - - - include - #relational-operator - - - include - #arithmetic-operator - - - include - #logic-operator - - - include - #assignment-operator - - - include - #storage-keyword - - - include - #function-call - - - include - #case-clause - - - include - #control-statement - - - - expression-operator - - match - =>|\b(delete|export|import|from|in|instanceof|new|typeof|void|as)\b - name - keyword.operator.js - - field-declaration - - begin - (?<!\()\s*((?:\b[a-zA-Z_$][\w$]*)|(?:\'[^']*\')|(?:\"[^"]*\"))\s*(\?\s*)?(?=(=|:)) - beginCaptures - - 1 - - name - variable.js - - 2 - - name - keyword.operator.js - - - end - (?=\}|;|,|$)|(?<=\}) - name - meta.field.declaration.js - patterns - - - include - #expression - - - - for-in-simple - - captures - - 1 - - name - storage.type.js - - 3 - - name - keyword.operator.js - - - match - (?<=\()\s*\b(var|let|const)\s+([a-zA-Z_$][\w$]*)\s+(in|of)\b - name - forin.expr.js - - function-call - - name - functioncall.expr.js - patterns - - - include - #await-modifier - - - include - #type-parameters - - - include - #paren-expression - - - - function-declaration - - begin - \b(?:(export)\s+)?(?:(async)\s+)?(function\b)(?:\s+([a-zA-Z_$][\w$]*))?\s* - beginCaptures - - 1 - - name - storage.modifier.js - - 2 - - name - storage.modifier.js - - 3 - - name - storage.type.function.js - - 4 - - name - entity.name.function.js - - - end - (?=;|\})|(?<=\}) - name - meta.function.js - patterns - - - include - #comment - - - include - #type-parameters - - - include - #function-type-parameters - - - include - #return-type - - - include - #function-overload-declaration - - - include - #decl-block - - - - function-overload-declaration - - captures - - 1 - - name - storage.modifier.js - - 2 - - name - storage.type.function.js - - 3 - - name - entity.name.function.js - - - match - \b(?:(export)\s+)?(function\b)(?:\s+([a-zA-Z_$][\w$]*))?\s* - name - meta.function.overload.js - - function-type-parameters - - begin - \( - beginCaptures - - 0 - - name - meta.brace.round.js - - - end - \) - endCaptures - - 0 - - name - meta.brace.round.js - - - name - meta.function.type.parameter.js - patterns - - - include - #comment - - - include - #parameter-name - - - include - #type-annotation - - - include - #variable-initializer - - - - indexer-declaration - - begin - \[ - beginCaptures - - 0 - - name - meta.brace.square.js - - - end - (\])\s*(\?\s*)?|$ - endCaptures - - 1 - - name - meta.brace.square.js - - 2 - - name - keyword.operator.js - - - name - meta.indexer.declaration.js - patterns - - - include - #type-annotation - - - include - #indexer-parameter - - - include - #expression - - - - indexer-parameter - - captures - - 1 - - name - variable.parameter.js - - - match - ([a-zA-Z_$][\w$]*)(?=\:) - name - meta.indexer.parameter.js - - jsx - - name - meta.jsx.js - patterns - - - include - #jsx-tag-without-attributes - - - include - #jsx-tag-open - - - include - #jsx-tag-close - - - include - #jsx-tag-invalid - - - begin - (?<=(?:'|"|})>) - end - (?=</) - name - meta.jsx.children.js - patterns - - - include - #jsx-children - - - - - - jsx-children - - patterns - - - include - #jsx-tag-without-attributes - - - include - #jsx-tag-open - - - include - #jsx-tag-close - - - include - #jsx-tag-invalid - - - include - #jsx-evaluated-code - - - include - #jsx-entities - - - - jsx-entities - - patterns - - - captures - - 1 - - name - punctuation.definition.entity.js - - 3 - - name - punctuation.definition.entity.js - - - match - (&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;) - name - constant.character.entity.js - - - match - & - name - invalid.illegal.bad-ampersand.js - - - - jsx-evaluated-code - - begin - { - beginCaptures - - 0 - - name - punctuation.definition.brace.curly.start.js - - - end - } - endCaptures - - 0 - - name - punctuation.definition.brace.curly.end.js - - - name - meta.brace.curly.js - patterns - - - include - #expression - - - - jsx-string-double-quoted - - begin - " - beginCaptures - - 0 - - name - punctuation.definition.string.begin.js - - - end - " - endCaptures - - 0 - - name - punctuation.definition.string.end.js - - - name - string.quoted.double.js - patterns - - - include - #jsx-entities - - - - jsx-string-single-quoted - - begin - ' - beginCaptures - - 0 - - name - punctuation.definition.string.begin.js - - - end - ' - endCaptures - - 0 - - name - punctuation.definition.string.end.js - - - name - string.quoted.single.js - patterns - - - include - #jsx-entities - - - - jsx-tag-attribute-assignment - - match - =(?=\s*(?:'|"|{|/\*|//|\n)) - name - keyword.operator.assignment.js - - jsx-tag-attribute-name - - captures - - 1 - - name - entity.other.attribute-name.js - - - match - (?x) - \s* - ([_$a-zA-Z][-$\w]*) - (?=\s|=|/?>|/\*|//) - name - meta.tag.attribute-name.js - - jsx-tag-attributes - - patterns - - - include - #jsx-tag-attribute-name - - - include - #jsx-tag-attribute-assignment - - - include - #jsx-string-double-quoted - - - include - #jsx-string-single-quoted - - - include - #jsx-evaluated-code - - - - jsx-tag-attributes-illegal - - match - \S+ - name - invalid.illegal.attribute.js - - jsx-tag-close - - begin - (</)([_$a-zA-Z][-$\w.]*(?<!\.|-)) - beginCaptures - - 1 - - name - punctuation.definition.tag.begin.js - - 2 - - name - entity.name.tag.js - - - end - (>) - endCaptures - - 1 - - name - punctuation.definition.tag.end.js - - - name - tag.close.js - patterns - - - include - #comment - - - - jsx-tag-invalid - - match - <\s*> - name - invalid.illegal.tag.incomplete.js - - jsx-tag-open - - begin - (?x) - (<) - ([_$a-zA-Z][-$\w.]*(?<!\.|-)) - (?=\s+(?!\?)|/?>) - beginCaptures - - 1 - - name - punctuation.definition.tag.begin.js - - 2 - - name - entity.name.tag.js - - - end - (/?>) - endCaptures - - 1 - - name - punctuation.definition.tag.end.js - - - name - tag.open.js - patterns - - - include - #comment - - - include - #jsx-tag-attributes - - - include - #jsx-tag-attributes-illegal - - - - jsx-tag-without-attributes - - begin - (<)([_$a-zA-Z][-$\w.]*(?<!\.|-))(>) - beginCaptures - - 1 - - name - punctuation.definition.tag.begin.js - - 2 - - name - entity.name.tag.js - - 3 - - name - punctuation.definition.tag.end.js - - - end - (</)([_$a-zA-Z][-$\w.]*(?<!\.|-))(>) - endCaptures - - 1 - - name - punctuation.definition.tag.begin.js - - 2 - - name - entity.name.tag.js - - 3 - - name - punctuation.definition.tag.end.js - - - name - tag.without-attributes.js - patterns - - - include - #jsx-children - - - - literal - - name - literal.js - patterns - - - include - #numeric-literal - - - include - #boolean-literal - - - include - #null-literal - - - include - #undefined-literal - - - include - #array-literal - - - include - #this-literal - - - - logic-operator - - match - \!|&|~|\||&&|\|\| - name - keyword.operator.arithmetic.js - - method-declaration - - begin - \b(?:(abstract)\s+)?\b(?:(public|private|protected)\s+)?\b(?:(async)\s+)?(?:(get|set)\s+)?(?:(new)|(?:([a-zA-Z_$][\.\w$]*)\s*(\??)))?\s*(?=\(|\<) - beginCaptures - - 1 - - name - storage.modifier.js - - 2 - - name - storage.modifier.js - - 3 - - name - storage.modifier.js - - 4 - - name - storage.type.property.js - - 5 - - name - keyword.operator.js - - 6 - - name - entity.name.function.js - - 7 - - name - keyword.operator.js - - - end - (?=\}|;|,)|(?<=\}) - name - meta.method.declaration.js - patterns - - - include - #comment - - - include - #type-parameters - - - include - #function-type-parameters - - - include - #type-annotation - - - include - #method-overload-declaration - - - include - #decl-block - - - - method-overload-declaration - - captures - - 1 - - name - storage.modifier.js - - 2 - - name - storage.modifier.js - - 3 - - name - storage.modifier.js - - 4 - - name - storage.type.property.js - - 5 - - name - keyword.operator.js - - 6 - - name - entity.name.function.js - - 7 - - name - keyword.operator.js - - - match - \b(?:(abstract)\s+)?\b(?:(public|private|protected)\s+)?\b(?:(async)\s+)?(?:(get|set)\s+)?(?:(new)|(?:([a-zA-Z_$][\.\w$]*)\s*(\??)))?\s*(?=\(|\<) - name - meta.method.overload.declaration.js - - new-expr - - begin - \b(new)\b - beginCaptures - - 1 - - name - keyword.operator.js - - - end - (?=[(;]|$) - name - new.expr.js - patterns - - - include - #type - - - include - #comment - - - - null-literal - - match - \b(null)\b - name - constant.language.null.js - - numeric-literal - - match - \b(?<=[^$])((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?))\b - name - constant.numeric.js - - object-body - - begin - \{ - beginCaptures - - 0 - - name - meta.brace.curly.js - - - end - \} - endCaptures - - 0 - - name - meta.brace.curly.js - - - name - meta.object.body.js - patterns - - - include - #string - - - include - #comment - - - include - #field-declaration - - - include - #method-declaration - - - include - #indexer-declaration - - - include - #type-annotation - - - include - #variable-initializer - - - include - #access-modifier - - - include - #static-modifier - - - include - #property-accessor - - - - object-declaration - - begin - \b(?:(export)\s+)?\b(?:(abstract)\s+)?\b(?<!\.)(class|interface)\b - beginCaptures - - 1 - - name - storage.modifier.js - - 2 - - name - storage.modifier.js - - 3 - - name - storage.type.js - - - end - (?<=\}) - endCaptures - - 1 - - name - brace.curly.js - - - name - meta.declaration.object.js - patterns - - - include - #comment - - - include - #object-heritage - - - include - #object-name - - - include - #type-parameters - - - include - #object-body - - - - object-heritage - - begin - (?:\b(extends|implements)) - beginCaptures - - 1 - - name - keyword.other.js - - - end - (?=\{) - endCaptures - - 1 - - name - brace.curly.js - - - name - meta.object.heritage.js - patterns - - - include - #comment - - - include - #object-heritage - - - include - #type-parameters - - - include - #object-heritage-parent - - - - object-heritage-parent - - captures - - 1 - - name - storage.type.js - - - match - (?:\s*([a-zA-Z_$][\w$]*)) - name - meta.object.heritage.parent.js - - object-member - - begin - [a-zA-Z_$][\w$]*\s*: - end - (?=,|\}) - name - meta.object.member.js - patterns - - - include - #expression - - - - object-name - - captures - - 0 - - name - entity.name.class.js - - - match - [a-zA-Z_$][\w$]* - name - meta.object.name.js - - parameter-name - - captures - - 1 - - name - storage.modifier.js - - 2 - - name - keyword.operator.js - - 3 - - name - variable.parameter.js - - 4 - - name - keyword.operator.js - - - match - (?:\s*\b(public|private|protected)\b\s+)?(\.\.\.)?\s*([a-zA-Z_$][\w$]*)\s*(\??) - name - parameter.name.js - - paren-expression - - begin - \( - beginCaptures - - 0 - - name - meta.brace.paren.js - - - end - \) - endCaptures - - 0 - - name - meta.brace.paren.js - - - patterns - - - include - #expression - - - - property-accessor - - match - \b(get|set)\b - name - storage.type.property.js - - qstring-double - - begin - " - end - "|(?=$) - name - string.double.js - patterns - - - include - #string-character-escape - - - - qstring-single - - begin - ' - end - '|(?=$) - name - string.single.js - patterns - - - include - #string-character-escape - - - - regex - - begin - (?<=[=(:,\[]|^|return|&&|\|\||!)\s*(/)(?![/*+{}?]) - end - $|(/)[igm]* - name - string.regex.js - patterns - - - match - \\. - name - constant.character.escape.js - - - match - \[(\\\]|[^\]])*\] - name - constant.character.class.js - - - - relational-operator - - match - ===|==|=|!=|!==|<=|>=|<>|<|> - name - keyword.operator.comparison.js - - return-type - - begin - (?<=\))\s*: - end - (?=$)|(?=\{|;|//) - name - meta.return.type.js - patterns - - - include - #type - - - - static-modifier - - match - \b(static)\b - name - keyword.other.js - - storage-keyword - - match - \b(number|boolean|string|any|var|let|function|const|module|namespace)\b - name - storage.type.js - - string - - name - string.js - patterns - - - include - #qstring-single - - - include - #qstring-double - - - - string-character-escape - - match - \\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.|$) - name - constant.character.escape - - switch-block - - begin - { - end - (?=\}) - name - switch-block.expr.js - patterns - - - include - #expression - - - - switch-expression - - begin - \b(switch)\b\s*\( - beginCaptures - - 1 - - name - keyword.operator.js - - - end - \) - name - switch-expression.expr.js - patterns - - - include - #expression - - - - switch-statement - - begin - (?=\bswitch\b\s*\() - end - } - name - switch-statement.expr.js - patterns - - - include - #switch-expression - - - include - #switch-block - - - - template - - begin - ` - beginCaptures - - 0 - - name - string.template.js - - - end - ` - endCaptures - - 0 - - name - string.template.js - - - name - meta.template.js - patterns - - - include - #template-substitution-element - - - include - #template-string-contents - - - - template-string-contents - - begin - .*? - end - (?=(\$\{|`)) - name - string.template.js - patterns - - - include - #string-character-escape - - - - template-substitution-element - - begin - \$\{ - beginCaptures - - 0 - - name - keyword.operator.js - - - end - \} - endCaptures - - 0 - - name - keyword.operator.js - - - name - template.element.js - patterns - - - include - #expression - - - - this-literal - - match - \b(this)\b - name - constant.language.this.js - - type - - name - meta.type.js - patterns - - - include - #type-primitive - - - include - #type-parameters - - - include - #type-tuple - - - include - #type-object - - - include - #type-operator - - - include - #type-paren-or-function-type-parameters - - - include - #type-function-return-type - - - include - #type-name - - - - type-annotation - - begin - : - end - (?=$|[,);\}\]]|//)|(?==[^>])|(?<=[\}>\]\)]|[a-zA-Z_$])\s*(?=\{) - name - meta.type.annotation.js - patterns - - - include - #type - - - include - #string - - - include - #comment - - - - type-declaration - - begin - \b(type)\b\s+([a-zA-Z_$][\w$]*)\s*=\s* - beginCaptures - - 1 - - name - keyword.other.js - - 2 - - name - storage.type.js - - - end - (?=$|[,);>]|var|type|function|class|interface) - name - meta.type.declaration.js - patterns - - - include - #type - - - - type-function-return-type - - begin - => - beginCaptures - - 0 - - name - keyword.operator.js - - - end - (?=\s*[,\)\{=;>]|//|$) - name - meta.type.function.return.js - patterns - - - include - #type - - - - type-name - - captures - - 1 - - name - entity.name.type.js - - - match - [a-zA-Z_$][.\w$]* - name - meta.type.name.js - - type-object - - begin - \{ - beginCaptures - - 0 - - name - meta.brace.curly.js - - - end - \} - endCaptures - - 0 - - name - meta.brace.curly.js - - - name - meta.object.type.js - patterns - - - include - #comment - - - include - #field-declaration - - - include - #method-declaration - - - include - #indexer-declaration - - - include - #type-annotation - - - - type-operator - - match - [.|] - name - keyword.operator.type.js - - type-parameters - - begin - ([a-zA-Z_$][\w$]*)?(<) - beginCaptures - - 1 - - name - entity.name.type.js - - 2 - - name - meta.brace.angle.js - - - end - (?=$)|(>) - endCaptures - - 2 - - name - meta.brace.angle.js - - - name - meta.type.parameters.js - patterns - - - match - \b(extends)\b - name - keyword.other.js - - - include - #comment - - - include - #type - - - - type-paren-or-function-type-parameters - - begin - (?:\b(new)\b)?\s*\( - beginCaptures - - 1 - - name - keyword.control.js - - - end - \) - name - meta.type.paren.cover.js - patterns - - - include - #comment - - - include - #type - - - include - #function-type-parameters - - - - type-primitive - - captures - - 1 - - name - storage.type.js - - - match - \b(string|number|boolean|symbol|any|void)\b - name - meta.type.primitive.js - - type-tuple - - begin - \[ - beginCaptures - - 0 - - name - meta.brace.square.js - - - end - \] - endCaptures - - 0 - - name - meta.brace.square.js - - - name - meta.type.tuple.js - patterns - - - include - #type - - - include - #comment - - - - undefined-literal - - match - \b(undefined)\b - name - constant.language.js - - var-expr - - begin - (?<!\()\s*\b(var|let|const(?!\s+enum)\b) - beginCaptures - - 1 - - name - storage.type.js - - - end - (?=$|;) - name - meta.var.expr.js - patterns - - - include - #var-single-variable - - - include - #comment - - - - var-single-variable - - begin - \b([a-zA-Z_$][\w$]*)\s*(=?) - beginCaptures - - 1 - - name - variable.js - - - end - (?=$|[;,]) - name - meta.var-single-variable.expr.js - patterns - - - include - #type-annotation - - - include - #string - - - include - #comment - - - include - #expression - - - - variable-initializer - - begin - (=) - beginCaptures - - 1 - - name - keyword.operator.js - - - end - (?=$|[,);=]) - patterns - - - include - #expression - - - - - scopeName - source.js - uuid - 805375ec-d614-41f5-8993-5843fe63ea82 - - - diff --git a/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/yaml.tmLanguage.json b/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/yaml.tmLanguage.json new file mode 100644 index 000000000..c3637dfc9 --- /dev/null +++ b/org.eclipse.tm4e.core/src/test/resources/org/eclipse/tm4e/core/yaml.tmLanguage.json @@ -0,0 +1,621 @@ +{ + "information_for_contributors": [ + "This file has been converted from https://github.com/textmate/yaml.tmbundle/blob/master/Syntaxes/YAML.tmLanguage", + "If you want to provide a fix or improvement, please create a pull request against the original repository.", + "Once accepted there, we are happy to receive an update request." + ], + "version": "https://github.com/textmate/yaml.tmbundle/commit/e54ceae3b719506dba7e481a77cea4a8b576ae46", + "name": "YAML", + "scopeName": "source.yaml", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#property" + }, + { + "include": "#directive" + }, + { + "match": "^---", + "name": "entity.other.document.begin.yaml" + }, + { + "match": "^\\.{3}", + "name": "entity.other.document.end.yaml" + }, + { + "include": "#node" + } + ], + "repository": { + "block-collection": { + "patterns": [ + { + "include": "#block-sequence" + }, + { + "include": "#block-mapping" + } + ] + }, + "block-mapping": { + "patterns": [ + { + "include": "#block-pair" + } + ] + }, + "block-node": { + "patterns": [ + { + "include": "#prototype" + }, + { + "include": "#block-scalar" + }, + { + "include": "#block-collection" + }, + { + "include": "#flow-scalar-plain-out" + }, + { + "include": "#flow-node" + } + ] + }, + "block-pair": { + "patterns": [ + { + "begin": "\\?", + "beginCaptures": { + "1": { + "name": "punctuation.definition.key-value.begin.yaml" + } + }, + "end": "(?=\\?)|^ *(:)|(:)", + "endCaptures": { + "1": { + "name": "punctuation.separator.key-value.mapping.yaml" + }, + "2": { + "name": "invalid.illegal.expected-newline.yaml" + } + }, + "name": "meta.block-mapping.yaml", + "patterns": [ + { + "include": "#block-node" + } + ] + }, + { + "begin": "(?x)\n (?=\n (?x:\n [^\\s[-?:,\\[\\]{}#&*!|>'\"%@`]]\n | [?:-] \\S\n )\n (\n [^\\s:]\n | : \\S\n | \\s+ (?![#\\s])\n )*\n \\s*\n :\n\t\t\t\t\t\t\t(\\s|$)\n )\n ", + "end": "(?x)\n (?=\n \\s* $\n | \\s+ \\#\n | \\s* : (\\s|$)\n )\n ", + "patterns": [ + { + "include": "#flow-scalar-plain-out-implicit-type" + }, + { + "begin": "(?x)\n [^\\s[-?:,\\[\\]{}#&*!|>'\"%@`]]\n | [?:-] \\S\n ", + "beginCaptures": { + "0": { + "name": "entity.name.tag.yaml" + } + }, + "contentName": "entity.name.tag.yaml", + "end": "(?x)\n (?=\n \\s* $\n | \\s+ \\#\n | \\s* : (\\s|$)\n )\n ", + "name": "string.unquoted.plain.out.yaml" + } + ] + }, + { + "match": ":(?=\\s|$)", + "name": "punctuation.separator.key-value.mapping.yaml" + } + ] + }, + "block-scalar": { + "begin": "(?:(\\|)|(>))([1-9])?([-+])?(.*\\n?)", + "beginCaptures": { + "1": { + "name": "keyword.control.flow.block-scalar.literal.yaml" + }, + "2": { + "name": "keyword.control.flow.block-scalar.folded.yaml" + }, + "3": { + "name": "constant.numeric.indentation-indicator.yaml" + }, + "4": { + "name": "storage.modifier.chomping-indicator.yaml" + }, + "5": { + "patterns": [ + { + "include": "#comment" + }, + { + "match": ".+", + "name": "invalid.illegal.expected-comment-or-newline.yaml" + } + ] + } + }, + "end": "^(?=\\S)|(?!\\G)", + "patterns": [ + { + "begin": "^([ ]+)(?! )", + "end": "^(?!\\1|\\s*$)", + "name": "string.unquoted.block.yaml" + } + ] + }, + "block-sequence": { + "match": "(-)(?!\\S)", + "name": "punctuation.definition.block.sequence.item.yaml" + }, + "comment": { + "begin": "(?:(^[ \\t]*)|[ \\t]+)(?=#\\p{Print}*$)", + "beginCaptures": { + "1": { + "name": "punctuation.whitespace.comment.leading.yaml" + } + }, + "end": "(?!\\G)", + "patterns": [ + { + "begin": "#", + "beginCaptures": { + "0": { + "name": "punctuation.definition.comment.yaml" + } + }, + "end": "\\n", + "name": "comment.line.number-sign.yaml" + } + ] + }, + "directive": { + "begin": "^%", + "beginCaptures": { + "0": { + "name": "punctuation.definition.directive.begin.yaml" + } + }, + "end": "(?=$|[ \\t]+($|#))", + "name": "meta.directive.yaml", + "patterns": [ + { + "captures": { + "1": { + "name": "keyword.other.directive.yaml.yaml" + }, + "2": { + "name": "constant.numeric.yaml-version.yaml" + } + }, + "match": "\\G(YAML)[ \\t]+(\\d+\\.\\d+)" + }, + { + "captures": { + "1": { + "name": "keyword.other.directive.tag.yaml" + }, + "2": { + "name": "storage.type.tag-handle.yaml" + }, + "3": { + "name": "support.type.tag-prefix.yaml" + } + }, + "match": "(?x)\n \\G\n (TAG)\n (?:[ \\t]+\n ((?:!(?:[0-9A-Za-z\\-]*!)?))\n (?:[ \\t]+ (\n ! (?x: %[0-9A-Fa-f]{2} | [0-9A-Za-z\\-#;/?:@&=+$,_.!~*'()\\[\\]] )*\n | (?![,!\\[\\]{}]) (?x: %[0-9A-Fa-f]{2} | [0-9A-Za-z\\-#;/?:@&=+$,_.!~*'()\\[\\]] )+\n )\n )?\n )?\n " + }, + { + "captures": { + "1": { + "name": "support.other.directive.reserved.yaml" + }, + "2": { + "name": "string.unquoted.directive-name.yaml" + }, + "3": { + "name": "string.unquoted.directive-parameter.yaml" + } + }, + "match": "(?x) \\G (\\w+) (?:[ \\t]+ (\\w+) (?:[ \\t]+ (\\w+))? )?" + }, + { + "match": "\\S+", + "name": "invalid.illegal.unrecognized.yaml" + } + ] + }, + "flow-alias": { + "captures": { + "1": { + "name": "keyword.control.flow.alias.yaml" + }, + "2": { + "name": "punctuation.definition.alias.yaml" + }, + "3": { + "name": "variable.other.alias.yaml" + }, + "4": { + "name": "invalid.illegal.character.anchor.yaml" + } + }, + "match": "((\\*))([^\\s\\[\\]/{/},]+)([^\\s\\]},]\\S*)?" + }, + "flow-collection": { + "patterns": [ + { + "include": "#flow-sequence" + }, + { + "include": "#flow-mapping" + } + ] + }, + "flow-mapping": { + "begin": "\\{", + "beginCaptures": { + "0": { + "name": "punctuation.definition.mapping.begin.yaml" + } + }, + "end": "\\}", + "endCaptures": { + "0": { + "name": "punctuation.definition.mapping.end.yaml" + } + }, + "name": "meta.flow-mapping.yaml", + "patterns": [ + { + "include": "#prototype" + }, + { + "match": ",", + "name": "punctuation.separator.mapping.yaml" + }, + { + "include": "#flow-pair" + } + ] + }, + "flow-node": { + "patterns": [ + { + "include": "#prototype" + }, + { + "include": "#flow-alias" + }, + { + "include": "#flow-collection" + }, + { + "include": "#flow-scalar" + } + ] + }, + "flow-pair": { + "patterns": [ + { + "begin": "\\?", + "beginCaptures": { + "0": { + "name": "punctuation.definition.key-value.begin.yaml" + } + }, + "end": "(?=[},\\]])", + "name": "meta.flow-pair.explicit.yaml", + "patterns": [ + { + "include": "#prototype" + }, + { + "include": "#flow-pair" + }, + { + "include": "#flow-node" + }, + { + "begin": ":(?=\\s|$|[\\[\\]{},])", + "beginCaptures": { + "0": { + "name": "punctuation.separator.key-value.mapping.yaml" + } + }, + "end": "(?=[},\\]])", + "patterns": [ + { + "include": "#flow-value" + } + ] + } + ] + }, + { + "begin": "(?x)\n (?=\n (?:\n [^\\s[-?:,\\[\\]{}#&*!|>'\"%@`]]\n | [?:-] [^\\s[\\[\\]{},]]\n )\n (\n [^\\s:[\\[\\]{},]]\n | : [^\\s[\\[\\]{},]]\n | \\s+ (?![#\\s])\n )*\n \\s*\n :\n\t\t\t\t\t\t\t(\\s|$)\n )\n ", + "end": "(?x)\n (?=\n \\s* $\n | \\s+ \\#\n | \\s* : (\\s|$)\n | \\s* : [\\[\\]{},]\n | \\s* [\\[\\]{},]\n )\n ", + "name": "meta.flow-pair.key.yaml", + "patterns": [ + { + "include": "#flow-scalar-plain-in-implicit-type" + }, + { + "begin": "(?x)\n [^\\s[-?:,\\[\\]{}#&*!|>'\"%@`]]\n | [?:-] [^\\s[\\[\\]{},]]\n ", + "beginCaptures": { + "0": { + "name": "entity.name.tag.yaml" + } + }, + "contentName": "entity.name.tag.yaml", + "end": "(?x)\n (?=\n \\s* $\n | \\s+ \\#\n | \\s* : (\\s|$)\n | \\s* : [\\[\\]{},]\n | \\s* [\\[\\]{},]\n )\n ", + "name": "string.unquoted.plain.in.yaml" + } + ] + }, + { + "include": "#flow-node" + }, + { + "begin": ":(?=\\s|$|[\\[\\]{},])", + "captures": { + "0": { + "name": "punctuation.separator.key-value.mapping.yaml" + } + }, + "end": "(?=[},\\]])", + "name": "meta.flow-pair.yaml", + "patterns": [ + { + "include": "#flow-value" + } + ] + } + ] + }, + "flow-scalar": { + "patterns": [ + { + "include": "#flow-scalar-double-quoted" + }, + { + "include": "#flow-scalar-single-quoted" + }, + { + "include": "#flow-scalar-plain-in" + } + ] + }, + "flow-scalar-double-quoted": { + "begin": "\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.yaml" + } + }, + "end": "\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.yaml" + } + }, + "name": "string.quoted.double.yaml", + "patterns": [ + { + "match": "\\\\([0abtnvfre \"/\\\\N_Lp]|x\\d\\d|u\\d{4}|U\\d{8})", + "name": "constant.character.escape.yaml" + }, + { + "match": "\\\\\\n", + "name": "constant.character.escape.double-quoted.newline.yaml" + } + ] + }, + "flow-scalar-plain-in": { + "patterns": [ + { + "include": "#flow-scalar-plain-in-implicit-type" + }, + { + "begin": "(?x)\n [^\\s[-?:,\\[\\]{}#&*!|>'\"%@`]]\n | [?:-] [^\\s[\\[\\]{},]]\n ", + "end": "(?x)\n (?=\n \\s* $\n | \\s+ \\#\n | \\s* : (\\s|$)\n | \\s* : [\\[\\]{},]\n | \\s* [\\[\\]{},]\n )\n ", + "name": "string.unquoted.plain.in.yaml" + } + ] + }, + "flow-scalar-plain-in-implicit-type": { + "patterns": [ + { + "captures": { + "1": { + "name": "constant.language.null.yaml" + }, + "2": { + "name": "constant.language.boolean.yaml" + }, + "3": { + "name": "constant.numeric.integer.yaml" + }, + "4": { + "name": "constant.numeric.float.yaml" + }, + "5": { + "name": "constant.other.timestamp.yaml" + }, + "6": { + "name": "constant.language.value.yaml" + }, + "7": { + "name": "constant.language.merge.yaml" + } + }, + "match": "(?x)\n (?x:\n (null|Null|NULL|~)\n | (y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)\n | (\n (?:\n [-+]? 0b [0-1_]+ # (base 2)\n | [-+]? 0 [0-7_]+ # (base 8)\n | [-+]? (?: 0|[1-9][0-9_]*) # (base 10)\n | [-+]? 0x [0-9a-fA-F_]+ # (base 16)\n | [-+]? [1-9] [0-9_]* (?: :[0-5]?[0-9])+ # (base 60)\n )\n )\n | (\n (?x:\n [-+]? (?: [0-9] [0-9_]*)? \\. [0-9.]* (?: [eE] [-+] [0-9]+)? # (base 10)\n | [-+]? [0-9] [0-9_]* (?: :[0-5]?[0-9])+ \\. [0-9_]* # (base 60)\n | [-+]? \\. (?: inf|Inf|INF) # (infinity)\n | \\. (?: nan|NaN|NAN) # (not a number)\n )\n )\n | (\n (?x:\n \\d{4} - \\d{2} - \\d{2} # (y-m-d)\n | \\d{4} # (year)\n - \\d{1,2} # (month)\n - \\d{1,2} # (day)\n (?: [Tt] | [ \\t]+) \\d{1,2} # (hour)\n : \\d{2} # (minute)\n : \\d{2} # (second)\n (?: \\.\\d*)? # (fraction)\n (?:\n (?:[ \\t]*) Z\n | [-+] \\d{1,2} (?: :\\d{1,2})?\n )? # (time zone)\n )\n )\n | (=)\n | (<<)\n )\n (?:\n (?=\n \\s* $\n | \\s+ \\#\n | \\s* : (\\s|$)\n | \\s* : [\\[\\]{},]\n | \\s* [\\[\\]{},]\n )\n )\n " + } + ] + }, + "flow-scalar-plain-out": { + "patterns": [ + { + "include": "#flow-scalar-plain-out-implicit-type" + }, + { + "begin": "(?x)\n [^\\s[-?:,\\[\\]{}#&*!|>'\"%@`]]\n | [?:-] \\S\n ", + "end": "(?x)\n (?=\n \\s* $\n | \\s+ \\#\n | \\s* : (\\s|$)\n )\n ", + "name": "string.unquoted.plain.out.yaml" + } + ] + }, + "flow-scalar-plain-out-implicit-type": { + "patterns": [ + { + "captures": { + "1": { + "name": "constant.language.null.yaml" + }, + "2": { + "name": "constant.language.boolean.yaml" + }, + "3": { + "name": "constant.numeric.integer.yaml" + }, + "4": { + "name": "constant.numeric.float.yaml" + }, + "5": { + "name": "constant.other.timestamp.yaml" + }, + "6": { + "name": "constant.language.value.yaml" + }, + "7": { + "name": "constant.language.merge.yaml" + } + }, + "match": "(?x)\n (?x:\n (null|Null|NULL|~)\n | (y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)\n | (\n (?:\n [-+]? 0b [0-1_]+ # (base 2)\n | [-+]? 0 [0-7_]+ # (base 8)\n | [-+]? (?: 0|[1-9][0-9_]*) # (base 10)\n | [-+]? 0x [0-9a-fA-F_]+ # (base 16)\n | [-+]? [1-9] [0-9_]* (?: :[0-5]?[0-9])+ # (base 60)\n )\n )\n | (\n (?x:\n [-+]? (?: [0-9] [0-9_]*)? \\. [0-9.]* (?: [eE] [-+] [0-9]+)? # (base 10)\n | [-+]? [0-9] [0-9_]* (?: :[0-5]?[0-9])+ \\. [0-9_]* # (base 60)\n | [-+]? \\. (?: inf|Inf|INF) # (infinity)\n | \\. (?: nan|NaN|NAN) # (not a number)\n )\n )\n | (\n (?x:\n \\d{4} - \\d{2} - \\d{2} # (y-m-d)\n | \\d{4} # (year)\n - \\d{1,2} # (month)\n - \\d{1,2} # (day)\n (?: [Tt] | [ \\t]+) \\d{1,2} # (hour)\n : \\d{2} # (minute)\n : \\d{2} # (second)\n (?: \\.\\d*)? # (fraction)\n (?:\n (?:[ \\t]*) Z\n | [-+] \\d{1,2} (?: :\\d{1,2})?\n )? # (time zone)\n )\n )\n | (=)\n | (<<)\n )\n (?x:\n (?=\n \\s* $\n | \\s+ \\#\n | \\s* : (\\s|$)\n )\n )\n " + } + ] + }, + "flow-scalar-single-quoted": { + "begin": "'", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.yaml" + } + }, + "end": "'(?!')", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.yaml" + } + }, + "name": "string.quoted.single.yaml", + "patterns": [ + { + "match": "''", + "name": "constant.character.escape.single-quoted.yaml" + } + ] + }, + "flow-sequence": { + "begin": "\\[", + "beginCaptures": { + "0": { + "name": "punctuation.definition.sequence.begin.yaml" + } + }, + "end": "\\]", + "endCaptures": { + "0": { + "name": "punctuation.definition.sequence.end.yaml" + } + }, + "name": "meta.flow-sequence.yaml", + "patterns": [ + { + "include": "#prototype" + }, + { + "match": ",", + "name": "punctuation.separator.sequence.yaml" + }, + { + "include": "#flow-pair" + }, + { + "include": "#flow-node" + } + ] + }, + "flow-value": { + "patterns": [ + { + "begin": "\\G(?![},\\]])", + "end": "(?=[},\\]])", + "name": "meta.flow-pair.value.yaml", + "patterns": [ + { + "include": "#flow-node" + } + ] + } + ] + }, + "node": { + "patterns": [ + { + "include": "#block-node" + } + ] + }, + "property": { + "begin": "(?=!|&)", + "end": "(?!\\G)", + "name": "meta.property.yaml", + "patterns": [ + { + "captures": { + "1": { + "name": "keyword.control.property.anchor.yaml" + }, + "2": { + "name": "punctuation.definition.anchor.yaml" + }, + "3": { + "name": "entity.name.type.anchor.yaml" + }, + "4": { + "name": "invalid.illegal.character.anchor.yaml" + } + }, + "match": "\\G((&))([^\\s\\[\\]/{/},]+)(\\S+)?" + }, + { + "match": "(?x)\n \\G\n (?:\n ! < (?: %[0-9A-Fa-f]{2} | [0-9A-Za-z\\-#;/?:@&=+$,_.!~*'()\\[\\]] )+ >\n | (?:!(?:[0-9A-Za-z\\-]*!)?) (?: %[0-9A-Fa-f]{2} | [0-9A-Za-z\\-#;/?:@&=+$_.~*'()] )+\n | !\n )\n (?=\\ |\\t|$)\n ", + "name": "storage.type.tag-handle.yaml" + }, + { + "match": "\\S+", + "name": "invalid.illegal.tag-handle.yaml" + } + ] + }, + "prototype": { + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#property" + } + ] + } + } +} \ No newline at end of file diff --git a/org.eclipse.tm4e.feature/feature.xml b/org.eclipse.tm4e.feature/feature.xml index 3a72d29f5..41a74fd68 100644 --- a/org.eclipse.tm4e.feature/feature.xml +++ b/org.eclipse.tm4e.feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/org.eclipse.tm4e.feature/pom.xml b/org.eclipse.tm4e.feature/pom.xml index 3c1cc94e0..f46e34610 100644 --- a/org.eclipse.tm4e.feature/pom.xml +++ b/org.eclipse.tm4e.feature/pom.xml @@ -7,5 +7,5 @@ org.eclipse.tm4e.feature eclipse-feature - 0.4.4-SNAPSHOT + 0.4.5-SNAPSHOT diff --git a/org.eclipse.tm4e.languageconfiguration.tests/.classpath b/org.eclipse.tm4e.languageconfiguration.tests/.classpath index a42a828e0..4222ea313 100644 --- a/org.eclipse.tm4e.languageconfiguration.tests/.classpath +++ b/org.eclipse.tm4e.languageconfiguration.tests/.classpath @@ -1,11 +1,34 @@ - + + + + + - + + + + + + + + + + + + + + + + + + + + - + diff --git a/org.eclipse.tm4e.languageconfiguration.tests/.gitignore b/org.eclipse.tm4e.languageconfiguration.tests/.gitignore deleted file mode 100644 index ae3c17260..000000000 --- a/org.eclipse.tm4e.languageconfiguration.tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/org.eclipse.tm4e.languageconfiguration.tests/.project b/org.eclipse.tm4e.languageconfiguration.tests/.project index 107994bc0..ea80c854b 100644 --- a/org.eclipse.tm4e.languageconfiguration.tests/.project +++ b/org.eclipse.tm4e.languageconfiguration.tests/.project @@ -20,9 +20,15 @@ + + org.eclipse.m2e.core.maven2Builder + + + - org.eclipse.pde.PluginNature org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.pde.PluginNature diff --git a/org.eclipse.tm4e.languageconfiguration.tests/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.tm4e.languageconfiguration.tests/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..f648802b5 --- /dev/null +++ b/org.eclipse.tm4e.languageconfiguration.tests/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,518 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.APILeak=warning +org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning +org.eclipse.jdt.core.compiler.problem.fallthroughCase=info +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=info +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=enabled +org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=11 +org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false +org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false +org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter=0 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type=49 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assertion_message=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0 +org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_record_components=16 +org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_type_annotations=0 +org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0 +org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch=0 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_constructor=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false +org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true +org.eclipse.jdt.core.formatter.comment.format_block_comments=false +org.eclipse.jdt.core.formatter.comment.format_header=true +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.indent_tag_description=false +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=120 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_not_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false +org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.text_block_indentation=0 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false +org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true +org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true +org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true +org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true +org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/org.eclipse.tm4e.languageconfiguration.tests/META-INF/MANIFEST.MF b/org.eclipse.tm4e.languageconfiguration.tests/META-INF/MANIFEST.MF index 91da0b012..494383737 100644 --- a/org.eclipse.tm4e.languageconfiguration.tests/META-INF/MANIFEST.MF +++ b/org.eclipse.tm4e.languageconfiguration.tests/META-INF/MANIFEST.MF @@ -15,7 +15,7 @@ Require-Bundle: org.junit;bundle-version="4.12.0", org.eclipse.ui.workbench, org.eclipse.ui.editors, org.eclipse.ui.workbench.texteditor, - org.eclipse.jface.text, + org.eclipse.jface.text;bundle-version="3.19", org.eclipse.ui Bundle-ActivationPolicy: lazy Import-Package: org.junit.jupiter.api diff --git a/org.eclipse.tm4e.languageconfiguration.tests/build.properties b/org.eclipse.tm4e.languageconfiguration.tests/build.properties index 2a3d80c33..8316739f4 100644 --- a/org.eclipse.tm4e.languageconfiguration.tests/build.properties +++ b/org.eclipse.tm4e.languageconfiguration.tests/build.properties @@ -1,5 +1,5 @@ -source.. = src/ -output.. = bin/ +source.. = src/main/java/,\ + src/main/resources/ bin.includes = META-INF/,\ .,\ plugin.xml,\ diff --git a/org.eclipse.tm4e.languageconfiguration.tests/language-configurations/language-configuration-no-linecomment.json b/org.eclipse.tm4e.languageconfiguration.tests/language-configurations/language-configuration-no-linecomment.json new file mode 100644 index 000000000..efcf41973 --- /dev/null +++ b/org.eclipse.tm4e.languageconfiguration.tests/language-configurations/language-configuration-no-linecomment.json @@ -0,0 +1,5 @@ +{ + "comments": { + "blockComment": [ "/*", "*/" ] + } +} diff --git a/org.eclipse.tm4e.languageconfiguration.tests/plugin.xml b/org.eclipse.tm4e.languageconfiguration.tests/plugin.xml index 177332244..f1356e3d2 100644 --- a/org.eclipse.tm4e.languageconfiguration.tests/plugin.xml +++ b/org.eclipse.tm4e.languageconfiguration.tests/plugin.xml @@ -10,6 +10,13 @@ name="Test Language Configuration content-type" priority="normal"> + + @@ -17,6 +24,10 @@ contentTypeId="org.eclipse.tm4e.languageconfiguration.tests.content-type1" path="language-configurations/language-configuration.json"> + + diff --git a/org.eclipse.tm4e.languageconfiguration.tests/src/org/eclipse/tm4e/languageconfiguration/tests/TestAutoClosing.java b/org.eclipse.tm4e.languageconfiguration.tests/src/main/java/org/eclipse/tm4e/languageconfiguration/tests/TestAutoClosing.java similarity index 100% rename from org.eclipse.tm4e.languageconfiguration.tests/src/org/eclipse/tm4e/languageconfiguration/tests/TestAutoClosing.java rename to org.eclipse.tm4e.languageconfiguration.tests/src/main/java/org/eclipse/tm4e/languageconfiguration/tests/TestAutoClosing.java diff --git a/org.eclipse.tm4e.languageconfiguration.tests/src/main/java/org/eclipse/tm4e/languageconfiguration/tests/TestComment.java b/org.eclipse.tm4e.languageconfiguration.tests/src/main/java/org/eclipse/tm4e/languageconfiguration/tests/TestComment.java new file mode 100644 index 000000000..b441dea08 --- /dev/null +++ b/org.eclipse.tm4e.languageconfiguration.tests/src/main/java/org/eclipse/tm4e/languageconfiguration/tests/TestComment.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2021 Red Hat Inc. and others. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.tm4e.languageconfiguration.tests; + +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayInputStream; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.texteditor.ITextEditor; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +public class TestComment { + + @AfterEach + public void tearDown() throws Exception { + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().closeAllEditors(false); + for (IProject p : ResourcesPlugin.getWorkspace().getRoot().getProjects()) { + p.delete(true, null); + } + } + + @Test + public void testIndentOnNewLine() throws Exception { + IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject(getClass().getName() + System.currentTimeMillis()); + p.create(null); + p.open(null); + IFile file = p.getFile("whatever.noLineComment"); + file.create(new ByteArrayInputStream("a\nb\nc".getBytes()), true, null); + ITextEditor editor = (ITextEditor) IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file, "org.eclipse.ui.genericeditor.GenericEditor"); + IDocument doc = editor.getDocumentProvider().getDocument(editor.getEditorInput()); + IHandlerService service = PlatformUI.getWorkbench().getService(IHandlerService.class); + editor.getSelectionProvider().setSelection(new TextSelection(0, 5)); + service.executeCommand("org.eclipse.tm4e.languageconfiguration.togglelinecommentcommand", null); + assertEquals("/*a*/\n/*b*/\n/*c*/", doc.get()); + } +} diff --git a/org.eclipse.tm4e.languageconfiguration.tests/src/org/eclipse/tm4e/languageconfiguration/tests/TestIndent.java b/org.eclipse.tm4e.languageconfiguration.tests/src/main/java/org/eclipse/tm4e/languageconfiguration/tests/TestIndent.java similarity index 100% rename from org.eclipse.tm4e.languageconfiguration.tests/src/org/eclipse/tm4e/languageconfiguration/tests/TestIndent.java rename to org.eclipse.tm4e.languageconfiguration.tests/src/main/java/org/eclipse/tm4e/languageconfiguration/tests/TestIndent.java diff --git a/org.eclipse.tm4e.core.tests/src/main/resources/.gitkeep b/org.eclipse.tm4e.languageconfiguration.tests/src/main/resources/.gitkeep similarity index 100% rename from org.eclipse.tm4e.core.tests/src/main/resources/.gitkeep rename to org.eclipse.tm4e.languageconfiguration.tests/src/main/resources/.gitkeep diff --git a/org.eclipse.tm4e.languageconfiguration/.classpath b/org.eclipse.tm4e.languageconfiguration/.classpath index 824bce586..3aa82bf3a 100644 --- a/org.eclipse.tm4e.languageconfiguration/.classpath +++ b/org.eclipse.tm4e.languageconfiguration/.classpath @@ -2,13 +2,39 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.eclipse.tm4e.languageconfiguration/.gitignore b/org.eclipse.tm4e.languageconfiguration/.gitignore deleted file mode 100644 index 934e0e06f..000000000 --- a/org.eclipse.tm4e.languageconfiguration/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/bin -/target diff --git a/org.eclipse.tm4e.languageconfiguration/.project b/org.eclipse.tm4e.languageconfiguration/.project index d56cfc773..cb625c415 100644 --- a/org.eclipse.tm4e.languageconfiguration/.project +++ b/org.eclipse.tm4e.languageconfiguration/.project @@ -20,9 +20,15 @@ + + org.eclipse.m2e.core.maven2Builder + + + - org.eclipse.pde.PluginNature org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.pde.PluginNature diff --git a/org.eclipse.tm4e.languageconfiguration/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.tm4e.languageconfiguration/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..6b99f88fc --- /dev/null +++ b/org.eclipse.tm4e.languageconfiguration/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,518 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.APILeak=warning +org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning +org.eclipse.jdt.core.compiler.problem.fallthroughCase=info +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=info +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=info +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=enabled +org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=11 +org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false +org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false +org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter=0 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type=49 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assertion_message=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0 +org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_record_components=16 +org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_type_annotations=0 +org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0 +org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch=0 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_constructor=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false +org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true +org.eclipse.jdt.core.formatter.comment.format_block_comments=false +org.eclipse.jdt.core.formatter.comment.format_header=true +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.indent_tag_description=false +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=120 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_not_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false +org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.text_block_indentation=0 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false +org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true +org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true +org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true +org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true +org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/org.eclipse.tm4e.languageconfiguration/META-INF/MANIFEST.MF b/org.eclipse.tm4e.languageconfiguration/META-INF/MANIFEST.MF index 16c5017ea..71dc936c5 100644 --- a/org.eclipse.tm4e.languageconfiguration/META-INF/MANIFEST.MF +++ b/org.eclipse.tm4e.languageconfiguration/META-INF/MANIFEST.MF @@ -4,13 +4,13 @@ Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-Localization: plugin Bundle-SymbolicName: org.eclipse.tm4e.languageconfiguration;singleton:=true -Bundle-Version: 0.4.0.qualifier +Bundle-Version: 0.4.1.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-11 Require-Bundle: org.eclipse.jface.text, org.eclipse.ui.genericeditor, com.google.gson, - org.eclipse.tm4e.core, - org.eclipse.tm4e.ui, + org.eclipse.tm4e.core;bundle-version="0.4.4", + org.eclipse.tm4e.ui;bundle-version="0.5.1", org.eclipse.core.runtime, org.eclipse.core.resources, org.eclipse.ui, diff --git a/org.eclipse.tm4e.languageconfiguration/build.properties b/org.eclipse.tm4e.languageconfiguration/build.properties index efe6aaa35..c63a44828 100644 --- a/org.eclipse.tm4e.languageconfiguration/build.properties +++ b/org.eclipse.tm4e.languageconfiguration/build.properties @@ -7,3 +7,9 @@ bin.includes = META-INF/,\ plugin.properties,\ resources/,\ about.html + +# https://codeiseasy.wordpress.com/2013/03/08/tycho-and-jdt-null-analysis/ +# JDT Null Analysis for Eclipse +additional.bundles = org.eclipse.jdt.annotation +# JDT Null Analysis types for Tycho +jars.extra.classpath = platform:/plugin/org.eclipse.jdt.annotation diff --git a/org.eclipse.tm4e.languageconfiguration/pom.xml b/org.eclipse.tm4e.languageconfiguration/pom.xml index 8726c136b..dc41a526e 100644 --- a/org.eclipse.tm4e.languageconfiguration/pom.xml +++ b/org.eclipse.tm4e.languageconfiguration/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.eclipse.tm4e.languageconfiguration eclipse-plugin - 0.4.0-SNAPSHOT + 0.4.1-SNAPSHOT org.eclipse org.eclipse.tm4e diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/HasLanguageConfigurationPropertyTester.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/HasLanguageConfigurationPropertyTester.java index dd68234f8..342cec892 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/HasLanguageConfigurationPropertyTester.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/HasLanguageConfigurationPropertyTester.java @@ -1,60 +1,63 @@ /** - * Copyright (c) 2018 Red Hat Inc. and others. + * Copyright (c) 2018 Red Hat Inc. and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * - * Contributors: - * Lucas Bullen (Red Hat Inc.) - initial API and implementation + * Contributors: + * Lucas Bullen (Red Hat Inc.) - initial API and implementation */ package org.eclipse.tm4e.languageconfiguration; import org.eclipse.core.expressions.PropertyTester; +import org.eclipse.core.runtime.Adapters; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.jface.text.IDocument; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationRegistryManager; -import org.eclipse.tm4e.ui.utils.ContentTypeHelper; -import org.eclipse.tm4e.ui.utils.ContentTypeInfo; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.tm4e.ui.internal.utils.ContentTypeHelper; +import org.eclipse.tm4e.ui.internal.utils.ContentTypeInfo; import org.eclipse.ui.texteditor.ITextEditor; public class HasLanguageConfigurationPropertyTester extends PropertyTester { + @Nullable + private static T adapt(@Nullable Object sourceObject, Class adapter) { + return Adapters.adapt(sourceObject, adapter); + } + @Override - public boolean test(Object receiver, String property, Object[] args, Object expectedValue) { - if (!(receiver instanceof ITextEditor)) { + public boolean test(@Nullable final Object receiver, @Nullable final String property, + final Object @Nullable [] args, @Nullable final Object expectedValue) { + final var editor = adapt(receiver, ITextEditor.class); + if (editor == null) { return false; } - ITextEditor editor = (ITextEditor) receiver; - IEditorInput input = editor.getEditorInput(); - IDocumentProvider docProvider = editor.getDocumentProvider(); + final var input = editor.getEditorInput(); + final var docProvider = editor.getDocumentProvider(); if (docProvider == null || input == null) { return false; } - IDocument document = docProvider.getDocument(input); + final var document = docProvider.getDocument(input); if (document == null) { return false; } - IContentType[] contentTypes; + final ContentTypeInfo info; try { - ContentTypeInfo info = ContentTypeHelper.findContentTypes(document); - if(info == null) { - return false; - } - contentTypes = info.getContentTypes(); - } catch (CoreException e) { + info = ContentTypeHelper.findContentTypes(document); + } catch (final CoreException e) { return false; } - LanguageConfigurationRegistryManager registry = LanguageConfigurationRegistryManager.getInstance(); - return registry.getLanguageConfigurationFor(contentTypes) != null; - } + if (info == null) { + return false; + } + final var registry = LanguageConfigurationRegistryManager.getInstance(); + return registry.getLanguageConfigurationFor(info.getContentTypes()) != null; + } } diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/ILanguageConfiguration.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/ILanguageConfiguration.java index ce80cb208..067fd3dae 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/ILanguageConfiguration.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/ILanguageConfiguration.java @@ -13,6 +13,7 @@ import java.util.List; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tm4e.languageconfiguration.internal.supports.AutoClosingPairConditional; import org.eclipse.tm4e.languageconfiguration.internal.supports.CharacterPair; import org.eclipse.tm4e.languageconfiguration.internal.supports.Comments; @@ -27,6 +28,7 @@ public interface ILanguageConfiguration { * * @return the language's comments or null if not set */ + @Nullable Comments getComments(); /** @@ -36,7 +38,8 @@ public interface ILanguageConfiguration { * @return the language's brackets. This configuration implicitly affects * pressing Enter around these brackets. */ - public List getBrackets(); + @Nullable + List getBrackets(); /** * Returns the language's auto closing pairs. The 'close' character is @@ -44,17 +47,19 @@ public interface ILanguageConfiguration { * configured brackets will be used. * * @return the language's auto closing pairs. The 'close' character is - * autautomatically inserted with the 'open' character is typed. If not + * automatically inserted with the 'open' character is typed. If not * set, the configured brackets will be used. */ - public List getAutoClosingPairs(); + @Nullable + List getAutoClosingPairs(); /** * Returns the language's rules to be evaluated when pressing Enter. * * @return the language's rules to be evaluated when pressing Enter. */ - public List getOnEnterRules(); + @Nullable + List getOnEnterRules(); /** * Returns the language's surrounding pairs. When the 'open' character is typed @@ -66,13 +71,15 @@ public interface ILanguageConfiguration { * close characters. If not set, the autoclosing pairs settings will be * used. */ - public List getSurroundingPairs(); + @Nullable + List getSurroundingPairs(); /** * Returns the language's folding rules. * * @return the language's folding or null if not set */ + @Nullable Folding getFolding(); /** @@ -81,5 +88,6 @@ public interface ILanguageConfiguration { * * @return the language's word pattern or null if not set */ + @Nullable String getWordPattern(); } diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/ILanguageConfigurationDefinition.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/ILanguageConfigurationDefinition.java index 68d759428..e6e1184b1 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/ILanguageConfigurationDefinition.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/ILanguageConfigurationDefinition.java @@ -12,6 +12,7 @@ package org.eclipse.tm4e.languageconfiguration; import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tm4e.registry.ITMResource; public interface ILanguageConfigurationDefinition extends ITMResource { @@ -28,6 +29,7 @@ public interface ILanguageConfigurationDefinition extends ITMResource { * * @return the language configuration. */ + @Nullable ILanguageConfiguration getLanguageConfiguration(); /** @@ -37,7 +39,7 @@ public interface ILanguageConfigurationDefinition extends ITMResource { * @return true if on enter is enabled, false * otherwise */ - Boolean isOnEnterEnabled(); + boolean isOnEnterEnabled(); /** * Set whether on-enter actions are enabled for this language configuration @@ -52,7 +54,7 @@ public interface ILanguageConfigurationDefinition extends ITMResource { * @return true if bracket auto closing is enabled, * false otherwise */ - Boolean isBracketAutoClosingEnabled(); + boolean isBracketAutoClosingEnabled(); /** * Set whether the bracket auto closing action is enabled for this language @@ -67,7 +69,7 @@ public interface ILanguageConfigurationDefinition extends ITMResource { * @return true if highlighting of matching pairs is enabled, * false otherwise */ - Boolean isMatchingPairsEnabled(); + boolean isMatchingPairsEnabled(); /** * Set whether the highlighting of matching pairs is enabled for this language diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/ILanguageConfigurationRegistryManager.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/ILanguageConfigurationRegistryManager.java index 51d0b7977..d470b3232 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/ILanguageConfigurationRegistryManager.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/ILanguageConfigurationRegistryManager.java @@ -12,6 +12,7 @@ package org.eclipse.tm4e.languageconfiguration; import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.jdt.annotation.Nullable; import org.osgi.service.prefs.BackingStoreException; /** @@ -65,6 +66,6 @@ public interface ILanguageConfigurationRegistryManager { * @return the {@link ILanguageConfiguration} for the given content type and * null otherwise. */ - ILanguageConfiguration getLanguageConfigurationFor(IContentType[] contentTypes); - + @Nullable + ILanguageConfiguration getLanguageConfigurationFor(IContentType... contentTypes); } diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/LanguageConfigurationAutoEditStrategy.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/LanguageConfigurationAutoEditStrategy.java index 1f3efa758..cec43f9eb 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/LanguageConfigurationAutoEditStrategy.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/LanguageConfigurationAutoEditStrategy.java @@ -1,238 +1,251 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.languageconfiguration; - -import java.util.Arrays; - -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy; -import org.eclipse.jface.text.DocumentCommand; -import org.eclipse.jface.text.IAutoEditStrategy; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.ITextViewer; -import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationRegistryManager; -import org.eclipse.tm4e.languageconfiguration.internal.supports.CharacterPair; -import org.eclipse.tm4e.languageconfiguration.internal.supports.EnterAction; -import org.eclipse.tm4e.languageconfiguration.internal.supports.EnterActionAndIndent; -import org.eclipse.tm4e.languageconfiguration.internal.utils.TabSpacesInfo; -import org.eclipse.tm4e.languageconfiguration.internal.utils.TextUtils; -import org.eclipse.tm4e.ui.utils.ContentTypeHelper; -import org.eclipse.tm4e.ui.utils.ContentTypeInfo; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.PlatformUI; - -/** - * {@link IAutoEditStrategy} which uses VSCode language-configuration.json. - * - */ -public class LanguageConfigurationAutoEditStrategy implements IAutoEditStrategy { - - private IDocument document; - private IContentType[] contentTypes; - - private TabSpacesInfo tabSpacesInfo; - private ITextViewer viewer; - - @Override - public void customizeDocumentCommand(IDocument document, DocumentCommand command) { - IContentType[] contentTypes = findContentTypes(document); - if (contentTypes == null || command.text.isEmpty()) { - return; - } - installViewer(); - - if (TextUtils.isEnter(document, command)) { - // key enter pressed - onEnter(document, command); - return; - } - - // Auto close pair - LanguageConfigurationRegistryManager registry = LanguageConfigurationRegistryManager.getInstance(); - for (IContentType contentType : contentTypes) { - CharacterPair autoClosingPair = registry.getAutoClosePair(document.get(), command.offset, command.text, - contentType); - if (autoClosingPair == null) { - continue; - } - command.caretOffset = command.offset + command.text.length(); - command.shiftsCaret = false; - if (command.text.equals(autoClosingPair.getKey()) && isFollowedBy(document, command.offset, autoClosingPair.getKey())) { - command.text = ""; - } else if (command.text.equals(autoClosingPair.getValue()) && isFollowedBy(document, command.offset, autoClosingPair.getValue())) { - command.text = ""; - } else { - command.text += autoClosingPair.getValue(); - } - return; - } - - Arrays.stream(contentTypes) - .flatMap(contentType -> registry.getEnabledAutoClosingPairs(contentType).stream()) - .map(CharacterPair::getValue) - .filter(command.text::equals) - .filter(closing -> isFollowedBy(document, command.offset, closing)) - .findFirst() - .ifPresent(closing -> { - command.caretOffset = command.offset + command.text.length(); - command.shiftsCaret = false; - command.text = ""; - }); - - } - - /** - * Returns true if the content after the given offset is followed - * by the given value and false otherwise. - * - * @param document the document - * @param offset the offset - * @param value the content value to check - * @return true if the content after the given offset is followed - * by the given value and false otherwise. - */ - private static boolean isFollowedBy(IDocument document, int offset, String value) { - for (int i = 0; i < value.length(); i++) { - if (document.getLength() <= offset) { - return false; - } - try { - if (document.getChar(offset) != value.charAt(i)) { - return false; - } - } catch (BadLocationException e) { - return false; - } - offset++; - } - return true; - } - - private void onEnter(IDocument document, DocumentCommand command) { - LanguageConfigurationRegistryManager registry = LanguageConfigurationRegistryManager.getInstance(); - for (IContentType contentType : contentTypes) { - if (!registry.shouldEnterAction(document, command.offset, contentType)) { - continue; - } - EnterActionAndIndent r = registry.getEnterAction(document, command.offset, contentType); - if (r != null) { - EnterAction enterAction = r.getEnterAction(); - String indentation = TextUtils.getIndentationFromWhitespace(r.getIndentation(), getTabSpaces()); - String delim = command.text; - switch (enterAction.getIndentAction()) { - case None: { - // Nothing special - String increasedIndent = normalizeIndentation(indentation + enterAction.getAppendText()); - String typeText = delim + increasedIndent; - - command.text = typeText; - command.shiftsCaret = false; - command.caretOffset = command.offset + (delim + increasedIndent).length(); - break; - } - case Indent: { - // Indent once - String increasedIndent = normalizeIndentation(indentation + enterAction.getAppendText()); - String typeText = delim + increasedIndent; - - command.text = typeText; - command.shiftsCaret = false; - command.caretOffset = command.offset + (delim + increasedIndent).length(); - break; - } - case IndentOutdent: { - // Ultra special - String normalIndent = normalizeIndentation(indentation); - String increasedIndent = normalizeIndentation(indentation + enterAction.getAppendText()); - - String typeText = delim + increasedIndent + delim + normalIndent; - command.text = typeText; - command.shiftsCaret = false; - command.caretOffset = command.offset + (delim + increasedIndent).length(); - break; - } - case Outdent: - String outdentedText = outdentString( - normalizeIndentation(indentation + enterAction.getAppendText())); - command.text = delim + outdentedText; - command.shiftsCaret = false; - command.caretOffset = command.offset + (delim + outdentedText).length(); - break; - } - return; - } - } - - // fail back to default for indentation - new DefaultIndentLineAutoEditStrategy().customizeDocumentCommand(document, command); - } - - private IContentType[] findContentTypes(IDocument document) { - if (this.document != null && this.document.equals(document)) { - return contentTypes; - } - try { - ContentTypeInfo info = ContentTypeHelper.findContentTypes(document); - this.contentTypes = info.getContentTypes(); - this.document = document; - } catch (CoreException e) { - e.printStackTrace(); - } - return contentTypes; - } - - private String outdentString(String str) { - if (str.startsWith("\t")) {//$NON-NLS-1$ - return str.substring(1); - } - TabSpacesInfo tabSpaces = getTabSpaces(); - if (tabSpaces.isInsertSpaces()) { - char[] chars = new char[tabSpaces.getTabSize()]; - Arrays.fill(chars, ' '); - String spaces = new String(chars); - if (str.startsWith(spaces)) { - return str.substring(spaces.length()); - } - } - return str; - } - - private String normalizeIndentation(String str) { - TabSpacesInfo tabSpaces = getTabSpaces(); - return TextUtils.normalizeIndentation(str, tabSpaces.getTabSize(), tabSpaces.isInsertSpaces()); - } - - private TabSpacesInfo getTabSpaces() { - // For performance reason, tab spaces info are cached. - // If user change preferences (tab size, insert spaces), he must close the - // editor - // FIXME : how to detect changes of (tab size, insert spaces) with a generic - // mean? - if (tabSpacesInfo != null) { - return tabSpacesInfo; - } - tabSpacesInfo = TextUtils.getTabSpaces(viewer); - return tabSpacesInfo; - } - - private void installViewer() { - if (viewer == null) { - IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - IEditorPart editorPart = page.getActiveEditor(); - viewer = editorPart.getAdapter(ITextViewer.class); - } - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.languageconfiguration; + +import java.util.Arrays; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy; +import org.eclipse.jface.text.DocumentCommand; +import org.eclipse.jface.text.IAutoEditStrategy; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationRegistryManager; +import org.eclipse.tm4e.languageconfiguration.internal.supports.CharacterPair; +import org.eclipse.tm4e.languageconfiguration.internal.supports.EnterAction; +import org.eclipse.tm4e.languageconfiguration.internal.utils.TabSpacesInfo; +import org.eclipse.tm4e.languageconfiguration.internal.utils.TextUtils; +import org.eclipse.tm4e.ui.internal.utils.ContentTypeHelper; +import org.eclipse.tm4e.ui.internal.utils.ContentTypeInfo; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PlatformUI; + +/** + * {@link IAutoEditStrategy} which uses VSCode language-configuration.json. + * + */ +public class LanguageConfigurationAutoEditStrategy implements IAutoEditStrategy { + + @Nullable + private IDocument document; + + private IContentType @Nullable [] contentTypes; + + @Nullable + private TabSpacesInfo tabSpacesInfo; + + @Nullable + private ITextViewer viewer; + + @Override + public void customizeDocumentCommand(@Nullable final IDocument document, @Nullable final DocumentCommand command) { + if (document == null || command == null) + return; + + final IContentType[] contentTypes = findContentTypes(document); + if (contentTypes == null || command.text.isEmpty()) { + return; + } + installViewer(); + + if (TextUtils.isEnter(document, command)) { + // key enter pressed + onEnter(document, command); + return; + } + + // Auto close pair + final LanguageConfigurationRegistryManager registry = LanguageConfigurationRegistryManager.getInstance(); + for (final IContentType contentType : contentTypes) { + final CharacterPair autoClosingPair = registry.getAutoClosePair(document.get(), command.offset, + command.text, + contentType); + if (autoClosingPair == null) { + continue; + } + command.caretOffset = command.offset + command.text.length(); + command.shiftsCaret = false; + if (command.text.equals(autoClosingPair.getKey()) + && isFollowedBy(document, command.offset, autoClosingPair.getKey())) { + command.text = ""; + } else if (command.text.equals(autoClosingPair.getValue()) + && isFollowedBy(document, command.offset, autoClosingPair.getValue())) { + command.text = ""; + } else { + command.text += autoClosingPair.getValue(); + } + return; + } + + Arrays.stream(contentTypes) + .flatMap(contentType -> registry.getEnabledAutoClosingPairs(contentType).stream()) + .map(CharacterPair::getValue) + .filter(command.text::equals) + .filter(closing -> isFollowedBy(document, command.offset, closing)) + .findFirst() + .ifPresent(closing -> { + command.caretOffset = command.offset + command.text.length(); + command.shiftsCaret = false; + command.text = ""; + }); + + } + + /** + * Returns true if the content after the given offset is followed + * by the given value and false otherwise. + * + * @param document the document + * @param offset the offset + * @param value the content value to check + * + * @return true if the content after the given offset is followed + * by the given value and false otherwise. + */ + private static boolean isFollowedBy(final IDocument document, int offset, final String value) { + for (int i = 0; i < value.length(); i++) { + if (document.getLength() <= offset) { + return false; + } + try { + if (document.getChar(offset) != value.charAt(i)) { + return false; + } + } catch (final BadLocationException e) { + return false; + } + offset++; + } + return true; + } + + private void onEnter(final IDocument document, final DocumentCommand command) { + final LanguageConfigurationRegistryManager registry = LanguageConfigurationRegistryManager.getInstance(); + if (contentTypes != null) { + for (final IContentType contentType : contentTypes) { + if (!registry.shouldEnterAction(document, command.offset, contentType)) { + continue; + } + final var enterIndent = registry.getEnterAction(document, command.offset, contentType); + if (enterIndent != null) { + final EnterAction enterAction = enterIndent.getEnterAction(); + final String indentation = TextUtils.getIndentationFromWhitespace(enterIndent.getIndentation(), + getTabSpaces()); + final String delim = command.text; + switch (enterAction.getIndentAction()) { + case None: { + // Nothing special + final String increasedIndent = normalizeIndentation(indentation + enterAction.getAppendText()); + final String typeText = delim + increasedIndent; + + command.text = typeText; + command.shiftsCaret = false; + command.caretOffset = command.offset + (delim + increasedIndent).length(); + break; + } + case Indent: { + // Indent once + final String increasedIndent = normalizeIndentation(indentation + enterAction.getAppendText()); + final String typeText = delim + increasedIndent; + + command.text = typeText; + command.shiftsCaret = false; + command.caretOffset = command.offset + (delim + increasedIndent).length(); + break; + } + case IndentOutdent: { + // Ultra special + final String normalIndent = normalizeIndentation(indentation); + final String increasedIndent = normalizeIndentation(indentation + enterAction.getAppendText()); + final String typeText = delim + increasedIndent + delim + normalIndent; + + command.text = typeText; + command.shiftsCaret = false; + command.caretOffset = command.offset + (delim + increasedIndent).length(); + break; + } + case Outdent: + final String outdentedText = outdentString( + normalizeIndentation(indentation + enterAction.getAppendText())); + + command.text = delim + outdentedText; + command.shiftsCaret = false; + command.caretOffset = command.offset + (delim + outdentedText).length(); + break; + } + return; + } + } + } + + // fail back to default for indentation + new DefaultIndentLineAutoEditStrategy().customizeDocumentCommand(document, command); + } + + private IContentType @Nullable [] findContentTypes(final IDocument document) { + if (this.document != null && this.document.equals(document)) { + return contentTypes; + } + try { + final ContentTypeInfo info = ContentTypeHelper.findContentTypes(document); + this.contentTypes = info == null ? null : info.getContentTypes(); + this.document = document; + } catch (final CoreException e) { + e.printStackTrace(); + } + return contentTypes; + } + + private String outdentString(final String str) { + if (str.startsWith("\t")) {//$NON-NLS-1$ + return str.substring(1); + } + final TabSpacesInfo tabSpaces = getTabSpaces(); + if (tabSpaces.isInsertSpaces()) { + final char[] chars = new char[tabSpaces.getTabSize()]; + Arrays.fill(chars, ' '); + final String spaces = new String(chars); + if (str.startsWith(spaces)) { + return str.substring(spaces.length()); + } + } + return str; + } + + private String normalizeIndentation(final String str) { + final TabSpacesInfo tabSpaces = getTabSpaces(); + return TextUtils.normalizeIndentation(str, tabSpaces.getTabSize(), tabSpaces.isInsertSpaces()); + } + + private TabSpacesInfo getTabSpaces() { + // For performance reason, tab spaces info are cached. + // If user change preferences (tab size, insert spaces), he must close the editor + // FIXME : how to detect changes of (tab size, insert spaces) with a generic mean? + if (tabSpacesInfo != null) { + return tabSpacesInfo; + } + tabSpacesInfo = TextUtils.getTabSpaces(viewer); + return tabSpacesInfo; + } + + private void installViewer() { + if (viewer == null) { + final IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + final IEditorPart editorPart = page.getActiveEditor(); + viewer = editorPart.getAdapter(ITextViewer.class); + } + } +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/LanguageConfigurationCharacterPairMatcher.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/LanguageConfigurationCharacterPairMatcher.java index 0eab91090..4f53077db 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/LanguageConfigurationCharacterPairMatcher.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/LanguageConfigurationCharacterPairMatcher.java @@ -1,143 +1,171 @@ -/** - * Copyright (c) 2018 Angelo ZERR. +/** + * Copyright (c) 2018 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.languageconfiguration; - -import java.util.List; - -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.source.DefaultCharacterPairMatcher; -import org.eclipse.jface.text.source.ICharacterPairMatcher; -import org.eclipse.jface.text.source.ICharacterPairMatcherExtension; -import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationRegistryManager; -import org.eclipse.tm4e.languageconfiguration.internal.supports.CharacterPair; -import org.eclipse.tm4e.ui.utils.ContentTypeHelper; -import org.eclipse.tm4e.ui.utils.ContentTypeInfo; - -/** - * Support of matching bracket with language configuration. - * - */ -public class LanguageConfigurationCharacterPairMatcher - implements ICharacterPairMatcher, ICharacterPairMatcherExtension { - - private DefaultCharacterPairMatcher matcher; - - private IDocument document; - - @Override - public IRegion match(IDocument document, int offset) { - DefaultCharacterPairMatcher matcher = getMatcher(document); - return matcher != null ? matcher.match(document, offset) : null; - } - - @Override - public IRegion match(IDocument document, int offset, int length) { - DefaultCharacterPairMatcher matcher = getMatcher(document); - return matcher != null ? matcher.match(document, offset, length) : null; - } - - @Override - public int getAnchor() { - return matcher != null ? matcher.getAnchor() : -1; - } - - @Override - public IRegion findEnclosingPeerCharacters(IDocument document, int offset, int length) { - DefaultCharacterPairMatcher matcher = getMatcher(document); - return matcher != null ? matcher.findEnclosingPeerCharacters(document, offset, length) : null; - } - - @Override - public boolean isMatchedChar(char ch) { - DefaultCharacterPairMatcher matcher = getMatcher(document); - return matcher != null ? matcher.isMatchedChar(ch) : false; - } - - @Override - public boolean isMatchedChar(char ch, IDocument document, int offset) { - DefaultCharacterPairMatcher matcher = getMatcher(document); - return matcher != null ? matcher.isMatchedChar(ch, document, offset) : false; - } - - @Override - public boolean isRecomputationOfEnclosingPairRequired(IDocument document, IRegion currentSelection, - IRegion previousSelection) { - DefaultCharacterPairMatcher matcher = getMatcher(document); - return matcher != null - ? matcher.isRecomputationOfEnclosingPairRequired(document, currentSelection, previousSelection) - : false; - } - - @Override - public void dispose() { - if (matcher != null) { - matcher.dispose(); - } - matcher = null; - } - - @Override - public void clear() { - if (matcher != null) { - matcher.clear(); - } - } - - /** - * Returns the matcher from the document. - * - * @param document - * @return - */ - private DefaultCharacterPairMatcher getMatcher(IDocument document) { - if (!document.equals(this.document)) { - matcher = null; - } - if (matcher == null) { - // initizalize a DefaultCharacterPairMatcher by using character pairs of the - // language configuration. - StringBuilder chars = new StringBuilder(); - this.document = document; - IContentType[] contentTypes = findContentTypes(document); - if (contentTypes != null) { - LanguageConfigurationRegistryManager registry = LanguageConfigurationRegistryManager.getInstance(); - for (IContentType contentType : contentTypes) { - if (!registry.shouldSurroundingPairs(document, -1, contentType)) { - continue; - } - List surroundingPairs = registry.getSurroundingPairs(contentType); - for (CharacterPair surroundingPair : surroundingPairs) { - chars.append(surroundingPair.getKey()); - chars.append(surroundingPair.getValue()); - } - } - } - matcher = new DefaultCharacterPairMatcher(chars.toString().toCharArray()); - } - return matcher; - } - - private IContentType[] findContentTypes(IDocument document) { - try { - ContentTypeInfo info = ContentTypeHelper.findContentTypes(document); - if(info != null) { - return info.getContentTypes(); - } - } catch (CoreException e) { - e.printStackTrace(); - } - return null; - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.languageconfiguration; + +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.source.DefaultCharacterPairMatcher; +import org.eclipse.jface.text.source.ICharacterPairMatcher; +import org.eclipse.jface.text.source.ICharacterPairMatcherExtension; +import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationRegistryManager; +import org.eclipse.tm4e.languageconfiguration.internal.supports.CharacterPair; +import org.eclipse.tm4e.ui.internal.utils.ContentTypeHelper; +import org.eclipse.tm4e.ui.internal.utils.ContentTypeInfo; + +/** + * Support of matching bracket with language configuration. + */ +public class LanguageConfigurationCharacterPairMatcher + implements ICharacterPairMatcher, ICharacterPairMatcherExtension { + + @Nullable + private DefaultCharacterPairMatcher matcher; + + @Nullable + private IDocument document; + + @Nullable + @Override + public IRegion match(@Nullable final IDocument document, final int offset) { + if (document == null) + return null; + final var matcher = getMatcher(document); + return matcher != null + ? matcher.match(document, offset) + : null; + } + + @Nullable + @Override + public IRegion match(@Nullable final IDocument document, final int offset, final int length) { + if (document == null) + return null; + final var matcher = getMatcher(document); + return matcher != null + ? matcher.match(document, offset, length) + : null; + } + + @Override + public int getAnchor() { + return matcher != null ? matcher.getAnchor() : -1; + } + + @Nullable + @Override + public IRegion findEnclosingPeerCharacters(@Nullable final IDocument document, final int offset, final int length) { + if (document == null) + return null; + final var matcher = getMatcher(document); + return matcher != null + ? matcher.findEnclosingPeerCharacters(document, offset, length) + : null; + } + + @Override + public boolean isMatchedChar(final char ch) { + final var document = this.document; + if (document == null) + return false; + final var matcher = getMatcher(document); + return matcher != null + ? matcher.isMatchedChar(ch) + : false; + } + + @Override + public boolean isMatchedChar(final char ch, @Nullable final IDocument document, final int offset) { + if (document == null) + return false; + final var matcher = getMatcher(document); + return matcher != null + ? matcher.isMatchedChar(ch, document, offset) + : false; + } + + @Override + public boolean isRecomputationOfEnclosingPairRequired(@Nullable final IDocument document, + @Nullable final IRegion currentSelection, @Nullable final IRegion previousSelection) { + if (document == null) + return false; + final var matcher = getMatcher(document); + return matcher != null + ? matcher.isRecomputationOfEnclosingPairRequired(document, currentSelection, previousSelection) + : false; + } + + @Override + public void dispose() { + if (matcher != null) { + matcher.dispose(); + } + matcher = null; + } + + @Override + public void clear() { + if (matcher != null) { + matcher.clear(); + } + } + + /** + * Returns the matcher from the document. + */ + @Nullable + private DefaultCharacterPairMatcher getMatcher(final IDocument document) { + if (!document.equals(this.document)) { + matcher = null; + } + if (matcher == null) { + // initialize a DefaultCharacterPairMatcher by using character pairs of the language configuration. + final var sb = new StringBuilder(); + this.document = document; + final IContentType[] contentTypes = findContentTypes(document); + if (contentTypes != null) { + final LanguageConfigurationRegistryManager registry = LanguageConfigurationRegistryManager + .getInstance(); + for (final IContentType contentType : contentTypes) { + if (!registry.shouldSurroundingPairs(document, -1, contentType)) { + continue; + } + final List surroundingPairs = registry.getSurroundingPairs(contentType); + for (final CharacterPair surroundingPair : surroundingPairs) { + sb.append(surroundingPair.getKey()); + sb.append(surroundingPair.getValue()); + } + } + } + final var chars = new char[sb.length()]; + sb.getChars(0, sb.length(), chars, 0); + matcher = new DefaultCharacterPairMatcher(chars); + } + return matcher; + } + + private IContentType @Nullable [] findContentTypes(final IDocument document) { + try { + final ContentTypeInfo info = ContentTypeHelper.findContentTypes(document); + if (info != null) { + return info.getContentTypes(); + } + } catch (final CoreException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/ToggleLineCommentHandler.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/ToggleLineCommentHandler.java index 0c68557c9..a225aaa4f 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/ToggleLineCommentHandler.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/ToggleLineCommentHandler.java @@ -1,40 +1,42 @@ /** - * Copyright (c) 2018 Red Hat Inc. and others. + * Copyright (c) 2018 Red Hat Inc. and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * - * Contributors: - * Lucas Bullen (Red Hat Inc.) - initial API and implementation + * Contributors: + * Lucas Bullen (Red Hat Inc.) - initial API and implementation */ package org.eclipse.tm4e.languageconfiguration; +import java.util.HashSet; +import java.util.Set; + import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.Command; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.Adapters; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IMultiTextSelection; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.IRewriteTarget; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.TextSelection; -import org.eclipse.jface.viewers.ISelection; import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationRegistryManager; import org.eclipse.tm4e.languageconfiguration.internal.supports.CharacterPair; import org.eclipse.tm4e.languageconfiguration.internal.supports.CommentSupport; import org.eclipse.tm4e.languageconfiguration.internal.utils.TextUtils; -import org.eclipse.tm4e.ui.utils.ContentTypeHelper; -import org.eclipse.tm4e.ui.utils.ContentTypeInfo; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorPart; +import org.eclipse.tm4e.ui.internal.utils.ContentTypeHelper; +import org.eclipse.tm4e.ui.internal.utils.ContentTypeInfo; import org.eclipse.ui.handlers.HandlerUtil; -import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; public class ToggleLineCommentHandler extends AbstractHandler { @@ -42,38 +44,49 @@ public class ToggleLineCommentHandler extends AbstractHandler { public static final String ADD_BLOCK_COMMENT_COMMAND_ID = "org.eclipse.tm4e.languageconfiguration.addblockcommentcommand"; public static final String REMOVE_BLOCK_COMMENT_COMMAND_ID = "org.eclipse.tm4e.languageconfiguration.removeblockcommentcommand"; + @Nullable + private static T adapt(@Nullable Object sourceObject, Class adapter) { + return Adapters.adapt(sourceObject, adapter); + } + + @Nullable @Override - public Object execute(ExecutionEvent event) throws ExecutionException { - IEditorPart part = HandlerUtil.getActiveEditor(event); - if (!(part instanceof ITextEditor)) { + public Object execute(@Nullable final ExecutionEvent event) throws ExecutionException { + if (event == null) { + return null; + } + final var part = HandlerUtil.getActiveEditor(event); + final var editor = adapt(part, ITextEditor.class); + if (editor == null) { return null; } - ITextEditor editor = (ITextEditor) part; - ISelection selection = editor.getSelectionProvider().getSelection(); + final var selection = editor.getSelectionProvider().getSelection(); if (!(selection instanceof ITextSelection)) { return null; } - ITextSelection textSelection = (ITextSelection) selection; - IEditorInput input = editor.getEditorInput(); - IDocumentProvider docProvider = editor.getDocumentProvider(); + final var textSelection = (ITextSelection) selection; + final var input = editor.getEditorInput(); + final var docProvider = editor.getDocumentProvider(); if (docProvider == null || input == null) { return null; } - IDocument document = docProvider.getDocument(input); + final var document = docProvider.getDocument(input); if (document == null) { return null; } - ContentTypeInfo info; + final ContentTypeInfo info; try { info = ContentTypeHelper.findContentTypes(document); - } catch (CoreException e) { + if (info == null) + return null; + } catch (final CoreException e) { return null; } - IContentType[] contentTypes = info.getContentTypes(); - Command command = event.getCommand(); - CommentSupport commentSupport = getCommentSupport(contentTypes); + final var contentTypes = info.getContentTypes(); + final var command = event.getCommand(); + final var commentSupport = getCommentSupport(contentTypes); if (commentSupport == null) { return null; } @@ -82,23 +95,51 @@ public Object execute(ExecutionEvent event) throws ExecutionException { return null; } - IRewriteTarget target = editor.getAdapter(IRewriteTarget.class); + final var target = adapt(editor, IRewriteTarget.class); if (target != null) { target.beginCompoundChange(); } try { - if (TOGGLE_LINE_COMMENT_COMMAND_ID.equals(command.getId()) && commentSupport.getLineComment() != null) { - updateLineComment(document, textSelection, commentSupport.getLineComment(), editor); - } else { - IRegion existingBlock = getBlockComment(document, textSelection, commentSupport); - if (ADD_BLOCK_COMMENT_COMMAND_ID.equals(command.getId()) && existingBlock == null) { - addBlockComment(document, textSelection, commentSupport.getBlockComment(), editor); - } else if (REMOVE_BLOCK_COMMENT_COMMAND_ID.equals(command.getId()) && existingBlock != null) { - removeBlockComment(document, textSelection, existingBlock, commentSupport.getBlockComment(), - editor); + switch (command.getId()) { + case TOGGLE_LINE_COMMENT_COMMAND_ID: { + final var lineComment = commentSupport.getLineComment(); + if (lineComment != null && !lineComment.isEmpty()) { + updateLineComment(document, textSelection, lineComment, editor); + } else { + final var blockComment = commentSupport.getBlockComment(); + if (blockComment != null) { + final Set lines = computeLines(textSelection, document); + for (final int line : lines) { + final int lineOffset = document.getLineOffset(line); + final int lineLength = document.getLineLength(line); + final ITextSelection range = new TextSelection(lineOffset, + line == document.getNumberOfLines() - 1 ? lineLength : lineLength - 1); + toggleBlockComment(document, range, commentSupport, editor); + } + } + } + break; + } + + case ADD_BLOCK_COMMENT_COMMAND_ID: { + final IRegion existingBlock = getBlockComment(document, textSelection, commentSupport); + final var blockComment = commentSupport.getBlockComment(); + if (existingBlock != null && blockComment != null) { + addBlockComment(document, textSelection, blockComment, editor); } + break; } - } catch (BadLocationException e) { + + case REMOVE_BLOCK_COMMENT_COMMAND_ID: { + final IRegion existingBlock = getBlockComment(document, textSelection, commentSupport); + final var blockComment = commentSupport.getBlockComment(); + if (existingBlock != null && blockComment != null) { + removeBlockComment(document, textSelection, existingBlock, blockComment, editor); + } + break; + } + } + } catch (final BadLocationException e) { // Caught by making no changes } finally { if (target != null) { @@ -108,41 +149,74 @@ public Object execute(ExecutionEvent event) throws ExecutionException { return null; } + private Set computeLines(final ITextSelection textSelection, final IDocument document) + throws BadLocationException { + final var regions = textSelection instanceof IMultiTextSelection + ? ((IMultiTextSelection) textSelection).getRegions() + : new IRegion[] { new Region(textSelection.getOffset(), textSelection.getLength()) }; + final var lines = new HashSet(); + for (final var region : regions) { + final int lineFrom = document.getLineOfOffset(region.getOffset()); + final int lineTo = document.getLineOfOffset(region.getOffset() + region.getLength()); + for (int line = lineFrom; line <= lineTo; line++) { + lines.add(line); + } + } + return lines; + } + + private void toggleBlockComment(final IDocument document, final ITextSelection textSelection, + final CommentSupport commentSupport, final ITextEditor editor) throws BadLocationException { + final var existingBlock = getBlockComment(document, textSelection, commentSupport); + final var blockComment = commentSupport.getBlockComment(); + if (blockComment == null) { + return; + } + if (existingBlock == null) { + addBlockComment(document, textSelection, blockComment, editor); + } else { + removeBlockComment(document, textSelection, existingBlock, blockComment, editor); + } + } + /** * Returns true if comment support is valid according the command to do and * false otherwise. - * + * * @param commentSupport * @param command + * * @return true if comment support is valid according the command to do and * false otherwise. */ - private boolean isValid(CommentSupport commentSupport, Command command) { - if (TOGGLE_LINE_COMMENT_COMMAND_ID.equals(command.getId())) { - // check if line comment is valid. - return commentSupport.getLineComment() != null && !commentSupport.getLineComment().isEmpty(); + private boolean isValid(final CommentSupport commentSupport, final Command command) { + final var lineComment = commentSupport.getLineComment(); + if (TOGGLE_LINE_COMMENT_COMMAND_ID.equals(command.getId()) && lineComment != null + && !lineComment.isEmpty()) { + return true; } // check if block comment is valid - CharacterPair characterPair = commentSupport.getBlockComment(); - return characterPair != null && characterPair.getKey() != null && !characterPair.getKey().isEmpty() - && characterPair.getValue() != null && !characterPair.getValue().isEmpty(); + final var blockComment = commentSupport.getBlockComment(); + return blockComment != null + && !"".equals(blockComment.getKey()) + && !"".equals(blockComment.getValue()); } /** - * Returns the comment support from the given list of content types and null - * otherwise. - * + * Returns the comment support from the given list of content types and null otherwise. + * * @param contentTypes - * @return the comment support from the given list of content types and null - * otherwise. + * + * @return the comment support from the given list of content types and null otherwise. */ - private CommentSupport getCommentSupport(IContentType[] contentTypes) { - LanguageConfigurationRegistryManager registry = LanguageConfigurationRegistryManager.getInstance(); - for (IContentType contentType : contentTypes) { + @Nullable + private CommentSupport getCommentSupport(final IContentType[] contentTypes) { + final var registry = LanguageConfigurationRegistryManager.getInstance(); + for (final var contentType : contentTypes) { if (!registry.shouldComment(contentType)) { continue; } - CommentSupport commentSupport = registry.getCommentSupport(contentType); + final var commentSupport = registry.getCommentSupport(contentType); if (commentSupport != null) { return commentSupport; } @@ -150,8 +224,8 @@ private CommentSupport getCommentSupport(IContentType[] contentTypes) { return null; } - private void updateLineComment(IDocument document, ITextSelection selection, String comment, ITextEditor editor) - throws BadLocationException { + private void updateLineComment(final IDocument document, final ITextSelection selection, final String comment, + final ITextEditor editor) throws BadLocationException { if (areLinesCommented(document, selection, comment)) { removeLineComments(document, selection, comment, editor); } else { @@ -159,11 +233,11 @@ private void updateLineComment(IDocument document, ITextSelection selection, Str } } - private boolean areLinesCommented(IDocument document, ITextSelection selection, String comment) + private boolean areLinesCommented(final IDocument document, final ITextSelection selection, final String comment) throws BadLocationException { int lineNumber = selection.getStartLine(); while (lineNumber <= selection.getEndLine()) { - IRegion lineRegion = document.getLineInformation(lineNumber); + final var lineRegion = document.getLineInformation(lineNumber); if (!document.get(lineRegion.getOffset(), lineRegion.getLength()).trim().startsWith(comment)) { return false; } @@ -172,16 +246,21 @@ private boolean areLinesCommented(IDocument document, ITextSelection selection, return true; } - private IRegion getBlockComment(IDocument document, ITextSelection selection, CommentSupport commentSupport) - throws BadLocationException { + @Nullable + private IRegion getBlockComment(final IDocument document, final ITextSelection selection, + final CommentSupport commentSupport) throws BadLocationException { if (selection.getText() == null) { return null; } - String text = document.get(); - String open = commentSupport.getBlockComment().getKey(); - String close = commentSupport.getBlockComment().getValue(); - int selectionStart = selection.getOffset(); - int selectionEnd = selectionStart + selection.getLength(); + final var blockComment = commentSupport.getBlockComment(); + if (blockComment == null) { + return null; + } + final String text = document.get(); + final String open = blockComment.getKey(); + final String close = blockComment.getValue(); + final int selectionStart = selection.getOffset(); + final int selectionEnd = selectionStart + selection.getLength(); int openOffset = TextUtils.startIndexOfOffsetTouchingString(text, selectionStart, open); if (openOffset == -1) { openOffset = text.lastIndexOf(open, selectionStart); @@ -193,7 +272,7 @@ private IRegion getBlockComment(IDocument document, ITextSelection selection, Co int closeOffset = TextUtils.startIndexOfOffsetTouchingString(text, selectionEnd, close); if (closeOffset == -1 || closeOffset < openOffset + open.length()) { closeOffset = text.indexOf(close, selectionEnd); - IRegion endLineRegion = document.getLineInformation(document.getLineOfOffset(selectionEnd)); + final IRegion endLineRegion = document.getLineInformation(document.getLineOfOffset(selectionEnd)); if (openOffset == -1 || closeOffset < openOffset + open.length() || closeOffset > endLineRegion.getOffset() + endLineRegion.getLength()) { return null; @@ -203,7 +282,7 @@ private IRegion getBlockComment(IDocument document, ITextSelection selection, Co // Make sure there isn't a different block closer before the one we found int othercloseOffset = text.indexOf(close, openOffset + open.length()); while (othercloseOffset != -1 && othercloseOffset < closeOffset) { - int startOfLineOffset = document.getLineOffset(document.getLineOfOffset(othercloseOffset)); + final int startOfLineOffset = document.getLineOffset(document.getLineOfOffset(othercloseOffset)); if (commentSupport.getLineComment() != null && text.substring(startOfLineOffset, othercloseOffset) .indexOf(commentSupport.getLineComment()) != -1) { return null; @@ -213,16 +292,16 @@ private IRegion getBlockComment(IDocument document, ITextSelection selection, Co return new Region(openOffset, closeOffset - openOffset); } - private void removeLineComments(IDocument document, ITextSelection selection, String comment, ITextEditor editor) - throws BadLocationException { + private void removeLineComments(final IDocument document, final ITextSelection selection, final String comment, + final ITextEditor editor) throws BadLocationException { int lineNumber = selection.getStartLine(); - int endLineNumber = selection.getEndLine(); - String oldText = document.get(); + final int endLineNumber = selection.getEndLine(); + final String oldText = document.get(); int deletedChars = 0; - Boolean isStartBeforeComment = false; + boolean isStartBeforeComment = false; while (lineNumber <= endLineNumber) { - int commentOffset = oldText.indexOf(comment, document.getLineOffset(lineNumber) + deletedChars); + final int commentOffset = oldText.indexOf(comment, document.getLineOffset(lineNumber) + deletedChars); document.replace(commentOffset - deletedChars, comment.length(), ""); if (deletedChars == 0) { isStartBeforeComment = commentOffset > selection.getOffset(); @@ -232,36 +311,32 @@ private void removeLineComments(IDocument document, ITextSelection selection, St } lineNumber++; } - ITextSelection newSelection = new TextSelection( + final var newSelection = new TextSelection( selection.getOffset() - (isStartBeforeComment ? 0 : comment.length()), selection.getLength() - deletedChars); editor.selectAndReveal(newSelection.getOffset(), newSelection.getLength()); } - private void addLineComments(IDocument document, ITextSelection selection, String comment, ITextEditor editor) - throws BadLocationException { - int lineNumber = selection.getStartLine(); - int endLineNumber = selection.getEndLine(); + private void addLineComments(final IDocument document, final ITextSelection selection, final String comment, + final ITextEditor editor) throws BadLocationException { int insertedChars = 0; - while (lineNumber <= endLineNumber) { + for (final int lineNumber : computeLines(selection, document)) { document.replace(document.getLineOffset(lineNumber), 0, comment); - if (lineNumber != endLineNumber) { - insertedChars += comment.length(); - } - lineNumber++; + insertedChars += comment.length(); } - ITextSelection newSelection = new TextSelection(selection.getOffset() + comment.length(), + final ITextSelection newSelection = new TextSelection(selection.getOffset() + comment.length(), selection.getLength() + insertedChars); editor.selectAndReveal(newSelection.getOffset(), newSelection.getLength()); } - private void removeBlockComment(IDocument document, ITextSelection selection, IRegion existingBlock, - CharacterPair blockComment, ITextEditor editor) throws BadLocationException { - int openOffset = existingBlock.getOffset(); - int openLength = blockComment.getKey().length(); - int closeOffset = existingBlock.getOffset() + existingBlock.getLength(); - int closeLength = blockComment.getValue().length(); + private void removeBlockComment(final IDocument document, final ITextSelection selection, + final IRegion existingBlock, final CharacterPair blockComment, final ITextEditor editor) + throws BadLocationException { + final int openOffset = existingBlock.getOffset(); + final int openLength = blockComment.getKey().length(); + final int closeOffset = existingBlock.getOffset() + existingBlock.getLength(); + final int closeLength = blockComment.getValue().length(); document.replace(openOffset, openLength, ""); document.replace(closeOffset - openLength, closeLength, ""); @@ -274,17 +349,17 @@ private void removeBlockComment(IDocument document, ITextSelection selection, IR if (selection.getOffset() + selection.getLength() > closeOffset) { lengthFix += selection.getOffset() + selection.getLength() - closeOffset; } - ITextSelection newSelection = new TextSelection(selection.getOffset() - offsetFix, + final var newSelection = new TextSelection(selection.getOffset() - offsetFix, selection.getLength() - lengthFix); editor.selectAndReveal(newSelection.getOffset(), newSelection.getLength()); } - private void addBlockComment(IDocument document, ITextSelection selection, CharacterPair blockComment, - ITextEditor editor) throws BadLocationException { + private void addBlockComment(final IDocument document, final ITextSelection selection, + final CharacterPair blockComment, final ITextEditor editor) throws BadLocationException { document.replace(selection.getOffset(), 0, blockComment.getKey()); document.replace(selection.getOffset() + selection.getLength() + blockComment.getKey().length(), 0, blockComment.getValue()); - ITextSelection newSelection = new TextSelection(selection.getOffset() + blockComment.getKey().length(), + final var newSelection = new TextSelection(selection.getOffset() + blockComment.getKey().length(), selection.getLength()); editor.selectAndReveal(newSelection.getOffset(), newSelection.getLength()); } diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/WorkingCopyLanguageConfigurationRegistryManager.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/WorkingCopyLanguageConfigurationRegistryManager.java index 05b011ed6..293d46424 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/WorkingCopyLanguageConfigurationRegistryManager.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/WorkingCopyLanguageConfigurationRegistryManager.java @@ -1,19 +1,20 @@ /** - * Copyright (c) 2018 Red Hat Inc. and others. + * Copyright (c) 2018 Red Hat Inc. and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * - * Contributors: - * Lucas Bullen (Red Hat Inc.) - initial API and implementation + * Contributors: + * Lucas Bullen (Red Hat Inc.) - initial API and implementation */ package org.eclipse.tm4e.languageconfiguration; import java.util.ArrayList; import java.util.List; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tm4e.languageconfiguration.internal.AbstractLanguageConfigurationRegistryManager; import org.osgi.service.prefs.BackingStoreException; @@ -21,37 +22,38 @@ public class WorkingCopyLanguageConfigurationRegistryManager extends AbstractLan private final ILanguageConfigurationRegistryManager manager; + @Nullable private List added; + @Nullable private List removed; - public WorkingCopyLanguageConfigurationRegistryManager(ILanguageConfigurationRegistryManager manager) { + public WorkingCopyLanguageConfigurationRegistryManager(final ILanguageConfigurationRegistryManager manager) { this.manager = manager; - load(); - } - private void load() { // Copy definitions - ILanguageConfigurationDefinition[] definitions = manager.getDefinitions(); - for (ILanguageConfigurationDefinition definition : definitions) { + final ILanguageConfigurationDefinition[] definitions = manager.getDefinitions(); + for (final ILanguageConfigurationDefinition definition : definitions) { super.registerLanguageConfigurationDefinition(definition); } } @Override - public void registerLanguageConfigurationDefinition(ILanguageConfigurationDefinition definition) { + public void registerLanguageConfigurationDefinition(final ILanguageConfigurationDefinition definition) { super.registerLanguageConfigurationDefinition(definition); + var added = this.added; if (added == null) { - added = new ArrayList<>(); + added = this.added = new ArrayList<>(); } added.add(definition); } @Override - public void unregisterLanguageConfigurationDefinition(ILanguageConfigurationDefinition definition) { + public void unregisterLanguageConfigurationDefinition(final ILanguageConfigurationDefinition definition) { super.unregisterLanguageConfigurationDefinition(definition); + var removed = this.added; if (removed == null) { - removed = new ArrayList<>(); + removed = this.removed = new ArrayList<>(); } if (added != null) { added.remove(definition); @@ -63,12 +65,12 @@ public void unregisterLanguageConfigurationDefinition(ILanguageConfigurationDefi @Override public void save() throws BackingStoreException { if (removed != null) { - for (ILanguageConfigurationDefinition definition : removed) { + for (final ILanguageConfigurationDefinition definition : removed) { manager.unregisterLanguageConfigurationDefinition(definition); } } if (added != null) { - for (ILanguageConfigurationDefinition definition : added) { + for (final ILanguageConfigurationDefinition definition : added) { manager.registerLanguageConfigurationDefinition(definition); } } @@ -76,5 +78,4 @@ public void save() throws BackingStoreException { manager.save(); } } - } diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/AbstractLanguageConfigurationRegistryManager.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/AbstractLanguageConfigurationRegistryManager.java index f93a85b8e..0ce038703 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/AbstractLanguageConfigurationRegistryManager.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/AbstractLanguageConfigurationRegistryManager.java @@ -17,29 +17,26 @@ import java.util.Set; import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tm4e.languageconfiguration.ILanguageConfiguration; import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationDefinition; import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationRegistryManager; public abstract class AbstractLanguageConfigurationRegistryManager implements ILanguageConfigurationRegistryManager { - protected final Map pluginDefinitions; - protected final Map userDefinitions; - public AbstractLanguageConfigurationRegistryManager() { - pluginDefinitions = new HashMap<>(); - userDefinitions = new HashMap<>(); - } + protected final Map pluginDefinitions = new HashMap<>(); + protected final Map userDefinitions = new HashMap<>(); @Override public ILanguageConfigurationDefinition[] getDefinitions() { - Set definitions = new HashSet<>(); - userDefinitions.values().forEach(definition -> definitions.add(definition)); - pluginDefinitions.values().forEach(definition -> definitions.add(definition)); - return definitions.toArray(new ILanguageConfigurationDefinition[definitions.size()]); + final Set definitions = new HashSet<>(); + userDefinitions.values().forEach(definitions::add); + pluginDefinitions.values().forEach(definitions::add); + return definitions.toArray(ILanguageConfigurationDefinition[]::new); } @Override - public void registerLanguageConfigurationDefinition(ILanguageConfigurationDefinition definition) { + public void registerLanguageConfigurationDefinition(final ILanguageConfigurationDefinition definition) { if (definition.getPluginId() == null) { userDefinitions.put(definition.getContentType(), definition); } else { @@ -48,7 +45,7 @@ public void registerLanguageConfigurationDefinition(ILanguageConfigurationDefini } @Override - public void unregisterLanguageConfigurationDefinition(ILanguageConfigurationDefinition definition) { + public void unregisterLanguageConfigurationDefinition(final ILanguageConfigurationDefinition definition) { if (definition.getPluginId() == null) { userDefinitions.remove(definition.getContentType()); } else { @@ -56,9 +53,10 @@ public void unregisterLanguageConfigurationDefinition(ILanguageConfigurationDefi } } + @Nullable @Override - public ILanguageConfiguration getLanguageConfigurationFor(IContentType[] contentTypes) { - for (IContentType contentType : contentTypes) { + public ILanguageConfiguration getLanguageConfigurationFor(final IContentType... contentTypes) { + for (final IContentType contentType : contentTypes) { if (userDefinitions.containsKey(contentType)) { return userDefinitions.get(contentType).getLanguageConfiguration(); } diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfiguration.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfiguration.java index f816df086..657c4c857 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfiguration.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfiguration.java @@ -1,279 +1,298 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.languageconfiguration.internal; - -import java.io.Reader; -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.tm4e.languageconfiguration.ILanguageConfiguration; -import org.eclipse.tm4e.languageconfiguration.internal.supports.AutoClosingPairConditional; -import org.eclipse.tm4e.languageconfiguration.internal.supports.CharacterPair; -import org.eclipse.tm4e.languageconfiguration.internal.supports.Comments; -import org.eclipse.tm4e.languageconfiguration.internal.supports.EnterAction; -import org.eclipse.tm4e.languageconfiguration.internal.supports.EnterAction.IndentAction; -import org.eclipse.tm4e.languageconfiguration.internal.supports.Folding; -import org.eclipse.tm4e.languageconfiguration.internal.supports.OnEnterRule; - -import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; - -/** - * VSCode language-configuration.json - * - * @see https://code.visualstudio.com/docs/extensionAPI/extension-points#_contributeslanguages - */ -public class LanguageConfiguration implements ILanguageConfiguration { - - /** - * Returns an instance of {@link LanguageConfiguration} loaded from the VSCode - * language-configuration.json file reader. - * - * @param reader - * @return an instance of {@link LanguageConfiguration} loaded from the VSCode - * language-configuration.json file reader. - */ - public static LanguageConfiguration load(Reader reader) { - return new GsonBuilder() - .registerTypeAdapter(OnEnterRule.class, (JsonDeserializer) (json, typeOfT, context) -> { - String beforeText = null; - String afterText = null; - EnterAction action = null; - if (json.isJsonObject()) { - JsonObject object = json.getAsJsonObject(); - beforeText = getAsString(object.get("beforeText")); //$NON-NLS-1$ - afterText = getAsString(object.get("afterText")); //$NON-NLS-1$ - JsonElement actionElement = object.get("action"); //$NON-NLS-1$ - if (actionElement != null && actionElement.isJsonObject()) { - JsonObject actionObject = actionElement.getAsJsonObject(); - IndentAction indentAction = IndentAction - .valueOf(getAsString(actionObject.get("indentAction"))); //$NON-NLS-1$ - Integer removeText = getAsInt(actionObject.get("removeText")); //$NON-NLS-1$ - String appendText = getAsString(actionObject.get("appendText")); //$NON-NLS-1$ - if (indentAction != null) { - action = new EnterAction(indentAction); - action.setAppendText(appendText); - action.setRemoveText(removeText); - } - } - } - if (beforeText == null || action == null) { - return null; - } - return new OnEnterRule(beforeText, afterText, action); - }).registerTypeAdapter(Comments.class, (JsonDeserializer) (json, typeOfT, context) -> { - // ex: {"lineComment": "//","blockComment": [ "/*", "*/" ]} - String lineComment = null; - CharacterPair blockComment = null; - if (json.isJsonObject()) { - JsonObject object = json.getAsJsonObject(); - lineComment = getAsString(object.get("lineComment")); //$NON-NLS-1$ - JsonElement blockCommentElement = object.get("blockComment"); //$NON-NLS-1$ - if (blockCommentElement != null && blockCommentElement.isJsonArray()) { - JsonArray blockCommentArray = blockCommentElement.getAsJsonArray(); - if (blockCommentArray.size() == 2) { - String blockCommentStart = getAsString(blockCommentArray.get(0)); - String blockCommentEnd = getAsString(blockCommentArray.get(1)); - if (blockCommentStart != null && blockCommentEnd != null) { - blockComment = new CharacterPair(blockCommentStart, blockCommentEnd); - } - } - } - } - if (lineComment == null && blockComment == null) { - return null; - } - return new Comments(lineComment, blockComment); - }).registerTypeAdapter(CharacterPair.class, - (JsonDeserializer) (json, typeOfT, context) -> { - String open = null; - String close = null; - if (json.isJsonArray()) { - // ex: ["{","}"] - JsonArray characterPairs = json.getAsJsonArray(); - if (characterPairs.size() == 2) { - open = getAsString(characterPairs.get(0)); - close = getAsString(characterPairs.get(1)); - } - } - if (open == null || close == null) { - return null; - } - return new CharacterPair(open, close); - }) - .registerTypeAdapter(AutoClosingPairConditional.class, - (JsonDeserializer) (json, typeOfT, context) -> { - List notInList = new ArrayList<>(); - String open = null; - String close = null; - if (json.isJsonArray()) { - // ex: ["{","}"] - JsonArray characterPairs = json.getAsJsonArray(); - if (characterPairs.size() == 2) { - open = getAsString(characterPairs.get(0)); - close = getAsString(characterPairs.get(1)); - } - } else if (json.isJsonObject()) { - // ex: {"open":"'","close":"'", "notIn": ["string", "comment"]} - JsonObject object = json.getAsJsonObject(); - open = getAsString(object.get("open")); //$NON-NLS-1$ - close = getAsString(object.get("close")); //$NON-NLS-1$ - JsonElement notInElement = object.get("notIn"); //$NON-NLS-1$ - if (notInElement != null && notInElement.isJsonArray()) { - JsonArray notInArray = notInElement.getAsJsonArray(); - notInArray.forEach(element -> { - String string = getAsString(element); - if (string != null) { - notInList.add(string); - } - }); - } - } - if (open == null || close == null) { - return null; - } - return new AutoClosingPairConditional(open, close, notInList); - }) - .registerTypeAdapter(Folding.class, (JsonDeserializer) (json, typeOfT, context) -> { - // ex: {"offSide": true, "markers": {"start": "^\\s*/", "end": "^\\s*"}} - boolean offSide = false; - String startMarker = null; - String endMarker = null; - if (json.isJsonObject()) { - JsonObject object = json.getAsJsonObject(); - offSide = getAsBoolean(object.get("offSide"), offSide); //$NON-NLS-1$ - JsonElement markersElement = object.get("markers"); //$NON-NLS-1$ - if (markersElement != null && markersElement.isJsonObject()) { - JsonObject markersObject = markersElement.getAsJsonObject(); - startMarker = getAsString(markersObject.get("start")); //$NON-NLS-1$ - endMarker = getAsString(markersObject.get("end")); //$NON-NLS-1$ - } - } - if (startMarker == null || endMarker == null) { - return null; - } - return new Folding(offSide, startMarker, endMarker); - }).create().fromJson(reader, LanguageConfiguration.class); - } - - private static String getAsString(JsonElement element) { - if (element == null) { - return null; - } - try { - return element.getAsString(); - } catch (Exception e) { - return null; - } - } - - private static Boolean getAsBoolean(JsonElement element, Boolean defaultValue) { - if (element == null) { - return defaultValue; - } - try { - return element.getAsBoolean(); - } catch (Exception e) { - return defaultValue; - } - } - - private static Integer getAsInt(JsonElement element) { - if (element == null) { - return null; - } - try { - return element.getAsInt(); - } catch (Exception e) { - return null; - } - } - - /** - * Defines the comment symbols - */ - private Comments comments; - - /** - * The language's brackets. This configuration implicitly affects pressing Enter - * around these brackets. - */ - private List brackets; - - /** - * The language's rules to be evaluated when pressing Enter. - */ - private List onEnterRules; - - /** - * The language's auto closing pairs. The 'close' character is automatically - * inserted with the 'open' character is typed. If not set, the configured - * brackets will be used. - */ - private List autoClosingPairs; - - /** - * The language's surrounding pairs. When the 'open' character is typed on a - * selection, the selected string is surrounded by the open and close - * characters. If not set, the autoclosing pairs settings will be used. - */ - private List surroundingPairs; - - /** - * Defines when and how code should be folded in the editor - */ - private Folding folding; - - /** - * Regex which defines what is considered to be a word in the programming - * language. - */ - private String wordPattern; - - @Override - public Comments getComments() { - return comments; - } - - @Override - public List getBrackets() { - return brackets; - } - - @Override - public List getAutoClosingPairs() { - return autoClosingPairs; - } - - @Override - public List getOnEnterRules() { - return onEnterRules; - } - - @Override - public List getSurroundingPairs() { - return surroundingPairs; - } - - @Override - public Folding getFolding() { - return folding; - } - - @Override - public String getWordPattern() { - return wordPattern; - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.languageconfiguration.internal; + +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.languageconfiguration.ILanguageConfiguration; +import org.eclipse.tm4e.languageconfiguration.internal.supports.AutoClosingPairConditional; +import org.eclipse.tm4e.languageconfiguration.internal.supports.CharacterPair; +import org.eclipse.tm4e.languageconfiguration.internal.supports.Comments; +import org.eclipse.tm4e.languageconfiguration.internal.supports.EnterAction; +import org.eclipse.tm4e.languageconfiguration.internal.supports.EnterAction.IndentAction; +import org.eclipse.tm4e.languageconfiguration.internal.supports.Folding; +import org.eclipse.tm4e.languageconfiguration.internal.supports.OnEnterRule; + +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +/** + * VSCode language-configuration.json + * + * @see + * code.visualstudio.com/docs/extensionAPI/extension-points#_contributeslanguages + */ +public final class LanguageConfiguration implements ILanguageConfiguration { + + + /** + * Returns an instance of {@link LanguageConfiguration} loaded from the VSCode + * language-configuration.json file reader. + * + * @param reader + * + * @return an instance of {@link LanguageConfiguration} loaded from the VSCode + * language-configuration.json file reader. + */ + @Nullable + public static LanguageConfiguration load(final Reader reader) { + return new GsonBuilder() + .registerTypeAdapter(OnEnterRule.class, (JsonDeserializer<@Nullable OnEnterRule>) (json, typeOfT, context) -> { + String beforeText = null; + String afterText = null; + EnterAction action = null; + if (json.isJsonObject()) { + final JsonObject object = json.getAsJsonObject(); + beforeText = getAsString(object.get("beforeText")); //$NON-NLS-1$ + afterText = getAsString(object.get("afterText")); //$NON-NLS-1$ + final JsonElement actionElement = object.get("action"); //$NON-NLS-1$ + if (actionElement != null && actionElement.isJsonObject()) { + final JsonObject actionObject = actionElement.getAsJsonObject(); + final String indentActionString = getAsString(actionObject.get("indentAction")); //$NON-NLS-1$ + if (indentActionString != null) { + final IndentAction indentAction = IndentAction.valueOf(indentActionString); + final Integer removeText = getAsInteger(actionObject.get("removeText")); //$NON-NLS-1$ + final String appendText = getAsString(actionObject.get("appendText")); //$NON-NLS-1$ + action = new EnterAction(indentAction); + action.setAppendText(appendText); + action.setRemoveText(removeText); + } + } + } + if (beforeText == null || action == null) { + return null; + } + return new OnEnterRule(beforeText, afterText, action); + }).registerTypeAdapter(Comments.class, (JsonDeserializer<@Nullable Comments>) (json, typeOfT, context) -> { + // ex: {"lineComment": "//","blockComment": [ "/*", "*/" ]} + String lineComment = null; + CharacterPair blockComment = null; + if (json.isJsonObject()) { + final JsonObject object = json.getAsJsonObject(); + lineComment = getAsString(object.get("lineComment")); //$NON-NLS-1$ + final JsonElement blockCommentElement = object.get("blockComment"); //$NON-NLS-1$ + if (blockCommentElement != null && blockCommentElement.isJsonArray()) { + final JsonArray blockCommentArray = blockCommentElement.getAsJsonArray(); + if (blockCommentArray.size() == 2) { + final String blockCommentStart = getAsString(blockCommentArray.get(0)); + final String blockCommentEnd = getAsString(blockCommentArray.get(1)); + if (blockCommentStart != null && blockCommentEnd != null) { + blockComment = new CharacterPair(blockCommentStart, blockCommentEnd); + } + } + } + } + if (lineComment == null && blockComment == null) { + return null; + } + return new Comments(lineComment, blockComment); + }).registerTypeAdapter(CharacterPair.class, + (JsonDeserializer<@Nullable CharacterPair>) (json, typeOfT, context) -> { + String open = null; + String close = null; + if (json.isJsonArray()) { + // ex: ["{","}"] + final JsonArray characterPairs = json.getAsJsonArray(); + if (characterPairs.size() == 2) { + open = getAsString(characterPairs.get(0)); + close = getAsString(characterPairs.get(1)); + } + } + if (open == null || close == null) { + return null; + } + return new CharacterPair(open, close); + }) + .registerTypeAdapter(AutoClosingPairConditional.class, + (JsonDeserializer<@Nullable AutoClosingPairConditional>) (json, typeOfT, context) -> { + final List notInList = new ArrayList<>(); + String open = null; + String close = null; + if (json.isJsonArray()) { + // ex: ["{","}"] + final JsonArray characterPairs = json.getAsJsonArray(); + if (characterPairs.size() == 2) { + open = getAsString(characterPairs.get(0)); + close = getAsString(characterPairs.get(1)); + } + } else if (json.isJsonObject()) { + // ex: {"open":"'","close":"'", "notIn": ["string", "comment"]} + final JsonObject object = json.getAsJsonObject(); + open = getAsString(object.get("open")); //$NON-NLS-1$ + close = getAsString(object.get("close")); //$NON-NLS-1$ + final JsonElement notInElement = object.get("notIn"); //$NON-NLS-1$ + if (notInElement != null && notInElement.isJsonArray()) { + final JsonArray notInArray = notInElement.getAsJsonArray(); + notInArray.forEach(element -> { + final String string = getAsString(element); + if (string != null) { + notInList.add(string); + } + }); + } + } + if (open == null || close == null) { + return null; + } + return new AutoClosingPairConditional(open, close, notInList); + }) + .registerTypeAdapter(Folding.class, (JsonDeserializer<@Nullable Folding>) (json, typeOfT, context) -> { + // ex: {"offSide": true, "markers": {"start": "^\\s*/", "end": "^\\s*"}} + boolean offSide = false; + String startMarker = null; + String endMarker = null; + if (json.isJsonObject()) { + final JsonObject object = json.getAsJsonObject(); + offSide = getAsBoolean(object.get("offSide"), offSide); //$NON-NLS-1$ + final JsonElement markersElement = object.get("markers"); //$NON-NLS-1$ + if (markersElement != null && markersElement.isJsonObject()) { + final JsonObject markersObject = markersElement.getAsJsonObject(); + startMarker = getAsString(markersObject.get("start")); //$NON-NLS-1$ + endMarker = getAsString(markersObject.get("end")); //$NON-NLS-1$ + } + } + if (startMarker == null || endMarker == null) { + return null; + } + return new Folding(offSide, startMarker, endMarker); + }).create().fromJson(reader, LanguageConfiguration.class); + } + + @Nullable + private static String getAsString(@Nullable final JsonElement element) { + if (element == null) { + return null; + } + try { + return element.getAsString(); + } catch (final Exception e) { + return null; + } + } + + private static boolean getAsBoolean(@Nullable final JsonElement element, final boolean defaultValue) { + if (element == null) { + return defaultValue; + } + try { + return element.getAsBoolean(); + } catch (final Exception e) { + return defaultValue; + } + } + + @Nullable + private static Integer getAsInteger(@Nullable final JsonElement element) { + if (element == null) { + return null; + } + try { + return element.getAsInt(); + } catch (final Exception e) { + return null; + } + } + + /** + * Defines the comment symbols + */ + @Nullable + private Comments comments; + + /** + * The language's brackets. This configuration implicitly affects pressing Enter around these brackets. + */ + @Nullable + private List brackets; + + /** + * The language's rules to be evaluated when pressing Enter. + */ + @Nullable + private List onEnterRules; + + /** + * The language's auto closing pairs. The 'close' character is automatically + * inserted with the 'open' character is typed. If not set, the configured + * brackets will be used. + */ + @Nullable + private List autoClosingPairs; + + /** + * The language's surrounding pairs. When the 'open' character is typed on a + * selection, the selected string is surrounded by the open and close + * characters. If not set, the autoclosing pairs settings will be used. + */ + @Nullable + private List surroundingPairs; + + /** + * Defines when and how code should be folded in the editor + */ + @Nullable + private Folding folding; + + /** + * Regex which defines what is considered to be a word in the programming language. + */ + @Nullable + private String wordPattern; + + @Nullable + @Override + public Comments getComments() { + return comments; + } + + @Nullable + @Override + public List getBrackets() { + return brackets; + } + + @Nullable + @Override + public List getAutoClosingPairs() { + return autoClosingPairs; + } + + @Nullable + @Override + public List getOnEnterRules() { + return onEnterRules; + } + + @Nullable + @Override + public List getSurroundingPairs() { + return surroundingPairs; + } + + @Nullable + @Override + public Folding getFolding() { + return folding; + } + + @Nullable + @Override + public String getWordPattern() { + return wordPattern; + } +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationDefinition.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationDefinition.java index d48f329a2..4ec3a531b 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationDefinition.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationDefinition.java @@ -1,159 +1,181 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.languageconfiguration.internal; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.Charset; - -import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.tm4e.languageconfiguration.ILanguageConfiguration; -import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationDefinition; -import org.eclipse.tm4e.languageconfiguration.internal.supports.CharacterPairSupport; -import org.eclipse.tm4e.languageconfiguration.internal.supports.CommentSupport; -import org.eclipse.tm4e.languageconfiguration.internal.supports.OnEnterSupport; -import org.eclipse.tm4e.registry.TMResource; -import org.eclipse.tm4e.registry.XMLConstants; -import org.eclipse.tm4e.ui.utils.ContentTypeHelper; - -/** - * Language configuration definition. - * - */ -public class LanguageConfigurationDefinition extends TMResource implements ILanguageConfigurationDefinition { - - private IContentType contentType; - private boolean onEnterEnabled = true; - private boolean bracketAutoClosingEnabled = true; - private boolean matchingPairsEnabled = true; - - private CharacterPairSupport characterPair; - private OnEnterSupport onEnter; - private CommentSupport comment; - - public LanguageConfigurationDefinition(IContentType contentType, String path) { - super(path); - this.contentType = contentType; - } - - public LanguageConfigurationDefinition(IConfigurationElement ce) { - super(ce); - this.contentType = ContentTypeHelper.getContentTypeById(ce.getAttribute(XMLConstants.CONTENT_TYPE_ID_ATTR)); - } - - /** - * Constructor for user preferences (loaded from Json with Gson). - */ - public LanguageConfigurationDefinition(IContentType contentType, String path, String pluginId, - boolean onEnterEnabled, boolean bracketAutoClosingEnabled, boolean matchingPairsEnabled) { - super(path, pluginId); - this.contentType = contentType; - this.onEnterEnabled = onEnterEnabled; - this.bracketAutoClosingEnabled = bracketAutoClosingEnabled; - this.matchingPairsEnabled = matchingPairsEnabled; - } - - /** - * Returns the "character pair" support and null otherwise. - * - * @return the "character pair" support and null otherwise. - */ - public CharacterPairSupport getCharacterPair() { - if (this.characterPair == null) { - ILanguageConfiguration conf = getLanguageConfiguration(); - if (conf != null) { - this.characterPair = new CharacterPairSupport(conf.getBrackets(), conf.getAutoClosingPairs(), - conf.getSurroundingPairs()); - } - } - return characterPair; - } - - /** - * Returns the "on enter" support and null otherwise. - * - * @return the "on enter" support and null otherwise. - */ - public OnEnterSupport getOnEnter() { - if (this.onEnter == null) { - ILanguageConfiguration conf = getLanguageConfiguration(); - if (conf != null && (conf.getBrackets() != null || conf.getOnEnterRules() != null)) { - this.onEnter = new OnEnterSupport(conf.getBrackets(), conf.getOnEnterRules()); - } - } - return onEnter; - } - - /** - * Returns the "commment" support and null otherwise. - * - * @return the "commment" support and null otherwise. - */ - public CommentSupport getCommentSupport() { - if (this.comment == null) { - ILanguageConfiguration conf = getLanguageConfiguration(); - if (conf != null) { - this.comment = new CommentSupport(conf.getComments()); - } - } - return comment; - } - - @Override - public IContentType getContentType() { - return contentType; - } - - @Override - public ILanguageConfiguration getLanguageConfiguration() { - try { - return LanguageConfiguration.load(new InputStreamReader(getInputStream(), Charset.defaultCharset())); - } catch (IOException e) { - LanguageConfigurationPlugin.getInstance().getLog().log(new Status(IStatus.ERROR, LanguageConfigurationPlugin.PLUGIN_ID, e.getMessage(), e)); - return null; - } - } - - @Override - public Boolean isOnEnterEnabled() { - return onEnterEnabled; - } - - @Override - public void setOnEnterEnabled(boolean onEnterEnabled) { - this.onEnterEnabled = onEnterEnabled; - } - - @Override - public Boolean isBracketAutoClosingEnabled() { - return bracketAutoClosingEnabled; - } - - @Override - public void setBracketAutoClosingEnabled(boolean bracketAutoClosingEnabled) { - this.bracketAutoClosingEnabled = bracketAutoClosingEnabled; - } - - @Override - public Boolean isMatchingPairsEnabled() { - return matchingPairsEnabled; - } - - @Override - public void setMatchingPairsEnabled(boolean matchingPairsEnabled) { - this.matchingPairsEnabled = matchingPairsEnabled; - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.languageconfiguration.internal; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.Charset; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.languageconfiguration.ILanguageConfiguration; +import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationDefinition; +import org.eclipse.tm4e.languageconfiguration.internal.supports.CharacterPairSupport; +import org.eclipse.tm4e.languageconfiguration.internal.supports.CommentSupport; +import org.eclipse.tm4e.languageconfiguration.internal.supports.OnEnterSupport; +import org.eclipse.tm4e.registry.TMResource; +import org.eclipse.tm4e.registry.XMLConstants; +import org.eclipse.tm4e.ui.internal.utils.ContentTypeHelper; + +/** + * Language configuration definition. + * + */ +public final class LanguageConfigurationDefinition extends TMResource implements ILanguageConfigurationDefinition { + + private final IContentType contentType; + private boolean onEnterEnabled = true; + private boolean bracketAutoClosingEnabled = true; + private boolean matchingPairsEnabled = true; + + @Nullable + private CharacterPairSupport characterPair; + + @Nullable + private OnEnterSupport onEnter; + + @Nullable + private CommentSupport comment; + + public LanguageConfigurationDefinition(final IContentType contentType, final String path) { + super(path); + this.contentType = contentType; + } + + public LanguageConfigurationDefinition(final IConfigurationElement ce) throws CoreException { + super(ce); + final var contentTypeId = ce.getAttribute(XMLConstants.CONTENT_TYPE_ID_ATTR); + final var contentType = ContentTypeHelper.getContentTypeById(contentTypeId); + if (contentType == null) + throw new CoreException( + new Status(IStatus.ERROR, LanguageConfiguration.class, + "Cannot load language configuration with unknown content type ID " + contentTypeId)); + this.contentType = contentType; + } + + /** + * Constructor for user preferences (loaded from Json with Gson). + */ + public LanguageConfigurationDefinition(final IContentType contentType, final String path, + @Nullable final String pluginId, + final boolean onEnterEnabled, final boolean bracketAutoClosingEnabled, final boolean matchingPairsEnabled) { + super(path, pluginId); + this.contentType = contentType; + this.onEnterEnabled = onEnterEnabled; + this.bracketAutoClosingEnabled = bracketAutoClosingEnabled; + this.matchingPairsEnabled = matchingPairsEnabled; + } + + /** + * Returns the "character pair" support and null otherwise. + * + * @return the "character pair" support and null otherwise. + */ + @Nullable + CharacterPairSupport getCharacterPair() { + if (this.characterPair == null) { + final ILanguageConfiguration conf = getLanguageConfiguration(); + if (conf != null) { + this.characterPair = new CharacterPairSupport(conf.getBrackets(), conf.getAutoClosingPairs(), + conf.getSurroundingPairs()); + } + } + return characterPair; + } + + /** + * Returns the "on enter" support and null otherwise. + * + * @return the "on enter" support and null otherwise. + */ + @Nullable + OnEnterSupport getOnEnter() { + if (this.onEnter == null) { + final ILanguageConfiguration conf = getLanguageConfiguration(); + if (conf != null && (conf.getBrackets() != null || conf.getOnEnterRules() != null)) { + this.onEnter = new OnEnterSupport(conf.getBrackets(), conf.getOnEnterRules()); + } + } + return onEnter; + } + + /** + * Returns the "commment" support and null otherwise. + * + * @return the "commment" support and null otherwise. + */ + @Nullable + CommentSupport getCommentSupport() { + if (this.comment == null) { + final ILanguageConfiguration conf = getLanguageConfiguration(); + if (conf != null) { + this.comment = new CommentSupport(conf.getComments()); + } + } + return comment; + } + + @Override + public IContentType getContentType() { + return contentType; + } + + @Nullable + @Override + public ILanguageConfiguration getLanguageConfiguration() { + try (var in = getInputStream()) { + return LanguageConfiguration.load(new InputStreamReader(in, Charset.defaultCharset())); + } catch (final IOException e) { + final var plugin = LanguageConfigurationPlugin.getInstance(); + if (plugin != null) { + plugin.getLog().log( + new Status(IStatus.ERROR, LanguageConfigurationPlugin.PLUGIN_ID, e.getMessage(), e)); + } + return null; + } + } + + @Override + public boolean isOnEnterEnabled() { + return onEnterEnabled; + } + + @Override + public void setOnEnterEnabled(final boolean onEnterEnabled) { + this.onEnterEnabled = onEnterEnabled; + } + + @Override + public boolean isBracketAutoClosingEnabled() { + return bracketAutoClosingEnabled; + } + + @Override + public void setBracketAutoClosingEnabled(final boolean bracketAutoClosingEnabled) { + this.bracketAutoClosingEnabled = bracketAutoClosingEnabled; + } + + @Override + public boolean isMatchingPairsEnabled() { + return matchingPairsEnabled; + } + + @Override + public void setMatchingPairsEnabled(final boolean matchingPairsEnabled) { + this.matchingPairsEnabled = matchingPairsEnabled; + } + +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationMessages.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationMessages.java index ddee01773..ff485a828 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationMessages.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationMessages.java @@ -1,75 +1,76 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.languageconfiguration.internal; - -import org.eclipse.osgi.util.NLS; - -/** - * Helper class to get NLSed messages. - * - */ -public class LanguageConfigurationMessages extends NLS { - - private static final String BUNDLE_NAME = "org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationMessages"; //$NON-NLS-1$ - - public static String AutoClosingPairConditionalTableWidget_notIn; - public static String CharacterPairsTableWidget_end; - public static String CharacterPairsTableWidget_start; - public static String LanguageConfigurationInfoWidget_autoClosingPairs; - public static String LanguageConfigurationInfoWidget_blockCommentsEnd; - public static String LanguageConfigurationInfoWidget_blockCommentsStart; - public static String LanguageConfigurationInfoWidget_brackets; - public static String LanguageConfigurationInfoWidget_comments; - public static String LanguageConfigurationInfoWidget_end; - public static String LanguageConfigurationInfoWidget_folding_title; - public static String LanguageConfigurationInfoWidget_lineComments; - public static String LanguageConfigurationInfoWidget_markers; - public static String LanguageConfigurationInfoWidget_offSide; - public static String LanguageConfigurationInfoWidget_offSide_tooltip; - public static String LanguageConfigurationInfoWidget_onEnterRules; - public static String LanguageConfigurationInfoWidget_start; - public static String LanguageConfigurationInfoWidget_surroundingPairs; - public static String LanguageConfigurationInfoWidget_wordPattern_message; - public static String LanguageConfigurationInfoWidget_wordPattern_title; - public static String LanguageConfigurationPreferencePage_contentType; - public static String LanguageConfigurationPreferencePage_title; - public static String LanguageConfigurationPreferencePage_description; - public static String LanguageConfigurationPreferencePage_description2; - public static String LanguageConfigurationPreferencePage_new; - public static String LanguageConfigurationPreferencePage_path; - public static String LanguageConfigurationPreferencePage_pluginId; - public static String LanguageConfigurationPreferencePage_remove; - public static String OnEnterRuleTableWidget_beforeText; - public static String OnEnterRuleTableWidget_afterText; - public static String OnEnterRuleTableWidget_indentAction; - public static String OnEnterRuleTableWidget_appendText; - public static String OnEnterRuleTableWidget_removeText; - public static String SelectLanguageConfigurationWizardPage_browse_fileSystem; - public static String SelectLanguageConfigurationWizardPage_browse_workspace; - public static String SelectLanguageConfigurationWizardPage_contentType; - public static String SelectLanguageConfigurationWizardPage_file; - public static String SelectLanguageConfigurationWizardPage_fileError_error; - public static String SelectLanguageConfigurationWizardPage_fileError_invalid; - public static String SelectLanguageConfigurationWizardPage_fileError_noSelection; - public static String SelectLanguageConfigurationWizardPage_contentTypeError_noSelection; - public static String SelectLanguageConfigurationWizardPage_contentTypeError_invalid; - public static String SelectLanguageConfigurationWizardPage_contentTypeWarning_duplicate; - public static String SelectLanguageConfigurationWizardPage_page_description; - public static String SelectLanguageConfigurationWizardPage_page_title; - public static String SelectLanguageConfigurationWizardPage_workspace_description; - public static String SelectLanguageConfigurationWizardPage_workspace_title; - - static { - NLS.initializeMessages(BUNDLE_NAME, LanguageConfigurationMessages.class); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.languageconfiguration.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.osgi.util.NLS; + +/** + * Helper class to get NLSed messages. + */ +@NonNullByDefault({}) +public final class LanguageConfigurationMessages extends NLS { + + private static final String BUNDLE_NAME = "org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationMessages"; //$NON-NLS-1$ + + public static String AutoClosingPairConditionalTableWidget_notIn; + public static String CharacterPairsTableWidget_end; + public static String CharacterPairsTableWidget_start; + public static String LanguageConfigurationInfoWidget_autoClosingPairs; + public static String LanguageConfigurationInfoWidget_blockCommentsEnd; + public static String LanguageConfigurationInfoWidget_blockCommentsStart; + public static String LanguageConfigurationInfoWidget_brackets; + public static String LanguageConfigurationInfoWidget_comments; + public static String LanguageConfigurationInfoWidget_end; + public static String LanguageConfigurationInfoWidget_folding_title; + public static String LanguageConfigurationInfoWidget_lineComments; + public static String LanguageConfigurationInfoWidget_markers; + public static String LanguageConfigurationInfoWidget_offSide; + public static String LanguageConfigurationInfoWidget_offSide_tooltip; + public static String LanguageConfigurationInfoWidget_onEnterRules; + public static String LanguageConfigurationInfoWidget_start; + public static String LanguageConfigurationInfoWidget_surroundingPairs; + public static String LanguageConfigurationInfoWidget_wordPattern_message; + public static String LanguageConfigurationInfoWidget_wordPattern_title; + public static String LanguageConfigurationPreferencePage_contentType; + public static String LanguageConfigurationPreferencePage_title; + public static String LanguageConfigurationPreferencePage_description; + public static String LanguageConfigurationPreferencePage_description2; + public static String LanguageConfigurationPreferencePage_new; + public static String LanguageConfigurationPreferencePage_path; + public static String LanguageConfigurationPreferencePage_pluginId; + public static String LanguageConfigurationPreferencePage_remove; + public static String OnEnterRuleTableWidget_beforeText; + public static String OnEnterRuleTableWidget_afterText; + public static String OnEnterRuleTableWidget_indentAction; + public static String OnEnterRuleTableWidget_appendText; + public static String OnEnterRuleTableWidget_removeText; + public static String SelectLanguageConfigurationWizardPage_browse_fileSystem; + public static String SelectLanguageConfigurationWizardPage_browse_workspace; + public static String SelectLanguageConfigurationWizardPage_contentType; + public static String SelectLanguageConfigurationWizardPage_file; + public static String SelectLanguageConfigurationWizardPage_fileError_error; + public static String SelectLanguageConfigurationWizardPage_fileError_invalid; + public static String SelectLanguageConfigurationWizardPage_fileError_noSelection; + public static String SelectLanguageConfigurationWizardPage_contentTypeError_noSelection; + public static String SelectLanguageConfigurationWizardPage_contentTypeError_invalid; + public static String SelectLanguageConfigurationWizardPage_contentTypeWarning_duplicate; + public static String SelectLanguageConfigurationWizardPage_page_description; + public static String SelectLanguageConfigurationWizardPage_page_title; + public static String SelectLanguageConfigurationWizardPage_workspace_description; + public static String SelectLanguageConfigurationWizardPage_workspace_title; + + static { + NLS.initializeMessages(BUNDLE_NAME, LanguageConfigurationMessages.class); + } + +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationPlugin.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationPlugin.java index 5945760fc..9b360068f 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationPlugin.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationPlugin.java @@ -1,41 +1,54 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.languageconfiguration.internal; - -import org.eclipse.ui.plugin.AbstractUIPlugin; -import org.osgi.framework.BundleContext; - -/** - * OSGi Activator for Language Configuration (VSCode - * language-configuration.json) Eclipse bundle. - * - */ -public class LanguageConfigurationPlugin extends AbstractUIPlugin { - - public static final String PLUGIN_ID = "org.eclipse.tm4e.languageconfiguration"; //$NON-NLS-1$ - - private static LanguageConfigurationPlugin INSTANCE = null; - - public static LanguageConfigurationPlugin getInstance() { - return INSTANCE; - } - - @Override public void start(BundleContext context) throws Exception { - super.start(context); - INSTANCE = this; - } - - @Override public void stop(BundleContext context) throws Exception { - INSTANCE = null; - super.stop(context); - } + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.languageconfiguration.internal; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * OSGi Activator for Language Configuration (VSCode + * language-configuration.json) Eclipse bundle. + * + */ +public final class LanguageConfigurationPlugin extends AbstractUIPlugin { + + public static final String PLUGIN_ID = "org.eclipse.tm4e.languageconfiguration"; //$NON-NLS-1$ + + @Nullable + private static LanguageConfigurationPlugin INSTANCE = null; + + @Nullable + static LanguageConfigurationPlugin getInstance() { + return INSTANCE; + } + + public static void log(IStatus status) { + final var plugin = LanguageConfigurationPlugin.INSTANCE; + if (plugin != null) { + plugin.getLog().log(status); + } + } + + @Override + public void start(@Nullable final BundleContext context) throws Exception { + super.start(context); + INSTANCE = this; + } + + @Override + public void stop(@Nullable final BundleContext context) throws Exception { + INSTANCE = null; + super.stop(context); + } } \ No newline at end of file diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationRegistryManager.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationRegistryManager.java index 5b2b1077f..0dde8b8ec 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationRegistryManager.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationRegistryManager.java @@ -1,14 +1,14 @@ /** - * Copyright (c) 2015-2018 Angelo ZERR and others. + * Copyright (c) 2015-2018 Angelo ZERR and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * - * Contributors: - * Angelo Zerr - initial API and implementation - * Lucas Bullen (Red Hat Inc.) - language configuration preferences + * Contributors: + * Angelo Zerr - initial API and implementation + * Lucas Bullen (Red Hat Inc.) - language configuration preferences */ package org.eclipse.tm4e.languageconfiguration.internal; @@ -16,11 +16,11 @@ import java.util.Collections; import java.util.List; -import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; @@ -37,11 +37,12 @@ import org.eclipse.tm4e.languageconfiguration.internal.utils.TextUtils; import org.osgi.service.prefs.BackingStoreException; -public class LanguageConfigurationRegistryManager extends AbstractLanguageConfigurationRegistryManager { +public final class LanguageConfigurationRegistryManager extends AbstractLanguageConfigurationRegistryManager { private static final String EXTENSION_LANGUAGE_CONFIGURATIONS = "languageConfigurations"; //$NON-NLS-1$ private static final String LANGUAGE_CONFIGURATION_ELT = "languageConfiguration"; //$NON-NLS-1$ + @Nullable private static LanguageConfigurationRegistryManager INSTANCE; public static LanguageConfigurationRegistryManager getInstance() { @@ -56,18 +57,20 @@ private static synchronized LanguageConfigurationRegistryManager createInstance( if (INSTANCE != null) { return INSTANCE; } - LanguageConfigurationRegistryManager manager = new LanguageConfigurationRegistryManager(); + final LanguageConfigurationRegistryManager manager = new LanguageConfigurationRegistryManager(); manager.load(); return manager; } - private LanguageConfigurationDefinition getDefinition(IContentType contentType) { + @Nullable + private LanguageConfigurationDefinition getDefinition(final IContentType contentType) { LanguageConfigurationDefinition bestFit = null; - for (ILanguageConfigurationDefinition iDefinition : getDefinitions()) { + for (final var iDefinition : getDefinitions()) { if (iDefinition instanceof LanguageConfigurationDefinition) { - LanguageConfigurationDefinition definition = (LanguageConfigurationDefinition) iDefinition; - if (contentType.isKindOf(definition.getContentType()) - && (bestFit == null || definition.getContentType().isKindOf(bestFit.getContentType()))) { + final var definition = (LanguageConfigurationDefinition) iDefinition; + final var definitionContentType = definition.getContentType(); + if (contentType.isKindOf(definitionContentType) + && (bestFit == null || definitionContentType.isKindOf(bestFit.getContentType()))) { bestFit = definition; } } @@ -76,87 +79,89 @@ private LanguageConfigurationDefinition getDefinition(IContentType contentType) return bestFit; } - public CharacterPair getAutoClosePair(String text, Integer offset, String newCharacter, IContentType contentType) { - LanguageConfigurationDefinition definition = getDefinition(contentType); + @Nullable + public CharacterPair getAutoClosePair(final String text, final int offset, final String newCharacter, + final IContentType contentType) { + final var definition = getDefinition(contentType); if (definition == null || !definition.isBracketAutoClosingEnabled()) { return null; } - CharacterPairSupport characterPairSupport = this._getCharacterPairSupport(contentType); + final CharacterPairSupport characterPairSupport = this._getCharacterPairSupport(contentType); return characterPairSupport == null ? null : characterPairSupport.getAutoClosePair(text, offset, newCharacter); } - public boolean shouldSurroundingPairs(IDocument document, int offset, IContentType contentType) { - LanguageConfigurationDefinition definition = getDefinition(contentType); + public boolean shouldSurroundingPairs(final IDocument document, final int offset, final IContentType contentType) { + final var definition = getDefinition(contentType); if (definition == null || !definition.isMatchingPairsEnabled()) { return false; } - CharacterPairSupport characterPairSupport = this._getCharacterPairSupport(contentType); + final var characterPairSupport = this._getCharacterPairSupport(contentType); return characterPairSupport != null; } - public boolean shouldEnterAction(IDocument document, int offset, IContentType contentType) { - LanguageConfigurationDefinition definition = getDefinition(contentType); + public boolean shouldEnterAction(final IDocument document, final int offset, final IContentType contentType) { + final var definition = getDefinition(contentType); if (definition == null || !definition.isOnEnterEnabled()) { return false; } - OnEnterSupport onEnterSupport = this._getOnEnterSupport(contentType); + final var onEnterSupport = this._getOnEnterSupport(contentType); return onEnterSupport != null; } - public boolean shouldComment(IContentType contentType) { - LanguageConfigurationDefinition definition = getDefinition(contentType); + public boolean shouldComment(final IContentType contentType) { + final var definition = getDefinition(contentType); if (definition == null || !definition.isOnEnterEnabled()) { return false; } - CommentSupport commentSupport = this.getCommentSupport(contentType); + final var commentSupport = this.getCommentSupport(contentType); if (commentSupport == null) { return false; } return true; } - public List getEnabledAutoClosingPairs(IContentType contentType) { - LanguageConfigurationDefinition definition = getDefinition(contentType); + public List getEnabledAutoClosingPairs(final IContentType contentType) { + final var definition = getDefinition(contentType); if (definition == null || !definition.isBracketAutoClosingEnabled()) { return Collections.emptyList(); } - CharacterPairSupport characterPairSupport = this._getCharacterPairSupport(contentType); + final var characterPairSupport = this._getCharacterPairSupport(contentType); if (characterPairSupport == null) { return Collections.emptyList(); } return characterPairSupport.getAutoClosingPairs(); } - public List getSurroundingPairs(IContentType contentType) { - CharacterPairSupport characterPairSupport = this._getCharacterPairSupport(contentType); + public List getSurroundingPairs(final IContentType contentType) { + final var characterPairSupport = this._getCharacterPairSupport(contentType); if (characterPairSupport == null) { return Collections.emptyList(); } return characterPairSupport.getSurroundingPairs(); } - public EnterActionAndIndent getEnterAction(IDocument document, int offset, IContentType contentType) { + @Nullable + public EnterActionAndIndent getEnterAction(final IDocument document, final int offset, + final IContentType contentType) { String indentation = TextUtils.getLinePrefixingWhitespaceAtPosition(document, offset); - // let scopedLineTokens = this.getScopedLineTokens(model, range.startLineNumber, - // range.startColumn); - OnEnterSupport onEnterSupport = this._getOnEnterSupport(contentType /* scopedLineTokens.languageId */); + // let scopedLineTokens = this.getScopedLineTokens(model, range.startLineNumber, range.startColumn); + final var onEnterSupport = this._getOnEnterSupport(contentType /* scopedLineTokens.languageId */); if (onEnterSupport == null) { return null; } try { - IRegion lineInfo = document.getLineInformationOfOffset(offset); + final IRegion lineInfo = document.getLineInformationOfOffset(offset); - // String scopeLineText = DocumentHelper.getLineTextOfOffset(document, offset, - // false); - String beforeEnterText = document.get(lineInfo.getOffset(), offset - lineInfo.getOffset()); + // String scopeLineText = DocumentHelper.getLineTextOfOffset(document, offset, false); + final String beforeEnterText = document.get(lineInfo.getOffset(), offset - lineInfo.getOffset()); String afterEnterText = null; // selection support // if (range.isEmpty()) { afterEnterText = document.get(offset, lineInfo.getLength() - (offset - lineInfo.getOffset())); // scopedLineText.substr(range.startColumn - // - 1 - - // scopedLineTokens.firstCharOffset); + // - 1 - + // scopedLineTokens.firstCharOffset); // } else { // const endScopedLineTokens = this.getScopedLineTokens(model, // range.endLineNumber, range.endColumn); @@ -164,7 +169,7 @@ public EnterActionAndIndent getEnterAction(IDocument document, int offset, ICont // - 1 - scopedLineTokens.firstCharOffset); // } - String oneLineAboveText = ""; //$NON-NLS-1$ + final String oneLineAboveText = ""; //$NON-NLS-1$ /* * let lineNumber = range.startLineNumber; let oneLineAboveText = ''; * @@ -180,59 +185,63 @@ public EnterActionAndIndent getEnterAction(IDocument document, int offset, ICont EnterAction enterResult = null; try { enterResult = onEnterSupport.onEnter(oneLineAboveText, beforeEnterText, afterEnterText); - } catch (Exception e) { + } catch (final Exception e) { // onUnexpectedError(e); } if (enterResult == null) { return null; - } else { - // Here we add `\t` to appendText first because enterAction is leveraging - // appendText and removeText to change indentation. - if (enterResult.getAppendText() == null) { - if ((enterResult.getIndentAction() == IndentAction.Indent) - || (enterResult.getIndentAction() == IndentAction.IndentOutdent)) { - enterResult.setAppendText("\t"); //$NON-NLS-1$ - } else { - enterResult.setAppendText(""); //$NON-NLS-1$ - } + } + + // Here we add `\t` to appendText first because enterAction is leveraging + // appendText and removeText to change indentation. + if (enterResult.getAppendText() == null) { + if ((enterResult.getIndentAction() == IndentAction.Indent) + || (enterResult.getIndentAction() == IndentAction.IndentOutdent)) { + enterResult.setAppendText("\t"); //$NON-NLS-1$ + } else { + enterResult.setAppendText(""); //$NON-NLS-1$ } } - if (enterResult.getRemoveText() != null) { - indentation = indentation.substring(0, indentation.length() - enterResult.getRemoveText()); + final var removeText = enterResult.getRemoveText(); + if (removeText != null) { + indentation = indentation.substring(0, indentation.length() - removeText); } return new EnterActionAndIndent(enterResult, indentation); - } catch (BadLocationException e1) { + } catch (final BadLocationException e1) { } return null; } - public CommentSupport getCommentSupport(IContentType contentType) { - LanguageConfigurationDefinition value = this.getDefinition(contentType); - if (value == null) { + @Nullable + public CommentSupport getCommentSupport(final IContentType contentType) { + final var definition = this.getDefinition(contentType); + if (definition == null) { return null; } - return value.getCommentSupport(); + return definition.getCommentSupport(); } - private OnEnterSupport _getOnEnterSupport(IContentType contentType) { - LanguageConfigurationDefinition value = this.getDefinition(contentType); - if (value == null) { + @Nullable + private OnEnterSupport _getOnEnterSupport(final IContentType contentType) { + final var definition = this.getDefinition(contentType); + if (definition == null) { return null; } - return value.getOnEnter(); + return definition.getOnEnter(); } - private CharacterPairSupport _getCharacterPairSupport(IContentType contentType) { - LanguageConfigurationDefinition value = this.getDefinition(contentType); - if (value == null) { + @Nullable + private CharacterPairSupport _getCharacterPairSupport(final IContentType contentType) { + final var definition = this.getDefinition(contentType); + if (definition == null) { return null; } - return value.getCharacterPair(); + return definition.getCharacterPair(); } private void load() { @@ -241,12 +250,18 @@ private void load() { } private void loadFromExtensionPoints() { - IConfigurationElement[] cf = Platform.getExtensionRegistry() - .getConfigurationElementsFor(LanguageConfigurationPlugin.PLUGIN_ID, EXTENSION_LANGUAGE_CONFIGURATIONS); - for (IConfigurationElement ce : cf) { - String name = ce.getName(); + final var config = Platform.getExtensionRegistry().getConfigurationElementsFor( + LanguageConfigurationPlugin.PLUGIN_ID, EXTENSION_LANGUAGE_CONFIGURATIONS); + for (final var configElem : config) { + final String name = configElem.getName(); if (LANGUAGE_CONFIGURATION_ELT.equals(name)) { - LanguageConfigurationDefinition delegate = new LanguageConfigurationDefinition(ce); + final LanguageConfigurationDefinition delegate; + try { + delegate = new LanguageConfigurationDefinition(configElem); + } catch (CoreException ex) { + LanguageConfigurationPlugin.log(ex.getStatus()); + continue; + } registerLanguageConfigurationDefinition(delegate); } } @@ -256,12 +271,11 @@ private void loadFromExtensionPoints() { private void loadFromPreferences() { // Load grammar definitions from the // "${workspace_loc}/metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.tm4e.languageconfiguration.prefs" - IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(LanguageConfigurationPlugin.PLUGIN_ID); - String json = prefs.get(PreferenceConstants.LANGUAGE_CONFIGURATIONS, null); + final var prefs = InstanceScope.INSTANCE.getNode(LanguageConfigurationPlugin.PLUGIN_ID); + final String json = prefs.get(PreferenceConstants.LANGUAGE_CONFIGURATIONS, null); if (json != null) { - ILanguageConfigurationDefinition[] definitions = PreferenceHelper - .loadLanguageConfigurationDefinitions(json); - for (ILanguageConfigurationDefinition definition : definitions) { + final var definitions = PreferenceHelper.loadLanguageConfigurationDefinitions(json); + for (final var definition : definitions) { registerLanguageConfigurationDefinition(definition); } } @@ -271,18 +285,17 @@ private void loadFromPreferences() { public void save() throws BackingStoreException { // Save grammar definitions in the // "${workspace_loc}/metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.tm4e.languageconfiguration.prefs" - List definitions = new ArrayList<>(); - userDefinitions.values().forEach(definition -> definitions.add(definition)); + final var definitions = new ArrayList(); + userDefinitions.values().forEach(definitions::add); pluginDefinitions.values().forEach(definition -> { if (!(definition.isBracketAutoClosingEnabled() && definition.isMatchingPairsEnabled() && definition.isOnEnterEnabled())) { definitions.add(definition); } }); - String json = PreferenceHelper.toJson(definitions); - IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(LanguageConfigurationPlugin.PLUGIN_ID); + final var json = PreferenceHelper.toJson(definitions); + final var prefs = InstanceScope.INSTANCE.getNode(LanguageConfigurationPlugin.PLUGIN_ID); prefs.put(PreferenceConstants.LANGUAGE_CONFIGURATIONS, json); prefs.flush(); } - } diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/package-info.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/package-info.java new file mode 100644 index 000000000..13c21ce9c --- /dev/null +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.languageconfiguration.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/LanguageConfigurationContentProvider.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/LanguageConfigurationContentProvider.java index 647b3db7a..30f65e07a 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/LanguageConfigurationContentProvider.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/LanguageConfigurationContentProvider.java @@ -11,21 +11,25 @@ */ package org.eclipse.tm4e.languageconfiguration.internal.preferences; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationRegistryManager; -public class LanguageConfigurationContentProvider implements IStructuredContentProvider { +final class LanguageConfigurationContentProvider implements IStructuredContentProvider { + private static final Object[] EMPTY = {}; + + @Nullable private ILanguageConfigurationRegistryManager registry; @Override - public Object[] getElements(Object input) { - return registry.getDefinitions(); + public Object[] getElements(@Nullable final Object input) { + return registry != null ? registry.getDefinitions() : EMPTY; } @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + public void inputChanged(@Nullable final Viewer viewer, @Nullable final Object oldInput, @Nullable final Object newInput) { registry = (ILanguageConfigurationRegistryManager) newInput; } diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/LanguageConfigurationLabelProvider.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/LanguageConfigurationLabelProvider.java index 777cef524..a020d5382 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/LanguageConfigurationLabelProvider.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/LanguageConfigurationLabelProvider.java @@ -1,36 +1,43 @@ /** - * Copyright (c) 2018 Red Hat Inc. and others. + * Copyright (c) 2018 Red Hat Inc. and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * - * Contributors: - * Lucas Bullen (Red Hat Inc.) - initial API and implementation + * Contributors: + * Lucas Bullen (Red Hat Inc.) - initial API and implementation */ package org.eclipse.tm4e.languageconfiguration.internal.preferences; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.swt.graphics.Image; import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationDefinition; -public class LanguageConfigurationLabelProvider extends LabelProvider implements ITableLabelProvider { +final class LanguageConfigurationLabelProvider extends LabelProvider implements ITableLabelProvider { + @Nullable @Override - public Image getColumnImage(Object element, int columnIndex) { + public Image getColumnImage(@Nullable final Object element, final int columnIndex) { return null; } + @Nullable @Override - public String getText(Object element) { + public String getText(@Nullable final Object element) { return getColumnText(element, 0); } + @Nullable @Override - public String getColumnText(Object element, int columnIndex) { - ILanguageConfigurationDefinition definition = (ILanguageConfigurationDefinition) element; + public String getColumnText(@Nullable final Object element, final int columnIndex) { + if (element == null) + return null; + + final ILanguageConfigurationDefinition definition = (ILanguageConfigurationDefinition) element; switch (columnIndex) { case 0: diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/LanguageConfigurationPreferencePage.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/LanguageConfigurationPreferencePage.java index 7e6c15741..1c45d640e 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/LanguageConfigurationPreferencePage.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/LanguageConfigurationPreferencePage.java @@ -1,293 +1,294 @@ -/** - * Copyright (c) 2015-2018 Angelo ZERR and others. +/** + * Copyright (c) 2015-2018 Angelo ZERR and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - * Lucas Bullen (Red Hat Inc.) - configuration viewing and editing - */ -package org.eclipse.tm4e.languageconfiguration.internal.preferences; - -import java.util.Collection; -import java.util.Collections; -import java.util.stream.Collectors; - -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.layout.TableColumnLayout; -import org.eclipse.jface.preference.PreferencePage; -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.jface.util.BidiUtils; -import org.eclipse.jface.viewers.ColumnWeightData; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.window.Window; -import org.eclipse.jface.wizard.WizardDialog; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationDefinition; -import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationRegistryManager; -import org.eclipse.tm4e.languageconfiguration.WorkingCopyLanguageConfigurationRegistryManager; -import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationMessages; -import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationRegistryManager; -import org.eclipse.tm4e.languageconfiguration.internal.widgets.ColumnSelectionAdapter; -import org.eclipse.tm4e.languageconfiguration.internal.widgets.ColumnViewerComparator; -import org.eclipse.tm4e.languageconfiguration.internal.widgets.LanguageConfigurationPreferencesWidget; -import org.eclipse.tm4e.languageconfiguration.internal.wizards.LanguageConfigurationImportWizard; -import org.eclipse.ui.IWorkbench; -import org.eclipse.ui.IWorkbenchPreferencePage; -import org.osgi.service.prefs.BackingStoreException; - -/** - * A language configuration preference page allows configuration of the language - * configuration It provides controls for adding, removing and changing language - * configuration as well as enablement, default management. - */ -public class LanguageConfigurationPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { - - public final static String PAGE_ID = "org.eclipse.tm4e.languageconfiguration.preferences.LanguageConfigurationPreferencePage"; //$NON-NLS-1$ - - private ILanguageConfigurationRegistryManager manager; - - private TableViewer definitionViewer; - - private Button definitionNewButton; - private Button definitionRemoveButton; - private LanguageConfigurationPreferencesWidget infoWidget; - - public LanguageConfigurationPreferencePage() { - super(); - setDescription(LanguageConfigurationMessages.LanguageConfigurationPreferencePage_description); - manager = new WorkingCopyLanguageConfigurationRegistryManager( - LanguageConfigurationRegistryManager.getInstance()); - } - - @Override - protected Control createContents(Composite ancestor) { - Composite parent = new Composite(ancestor, SWT.NONE); - GridLayout layout = new GridLayout(); - layout.numColumns = 2; - layout.marginHeight = 0; - layout.marginWidth = 0; - parent.setLayout(layout); - - Composite innerParent = new Composite(parent, SWT.NONE); - GridLayout innerLayout = new GridLayout(); - innerLayout.numColumns = 2; - innerLayout.marginHeight = 0; - innerLayout.marginWidth = 0; - innerParent.setLayout(innerLayout); - GridData gd = new GridData(GridData.FILL_BOTH); - gd.horizontalSpan = 2; - innerParent.setLayoutData(gd); - - createDefinitionsListContent(parent); - - definitionViewer.setInput(manager); - - infoWidget = new LanguageConfigurationPreferencesWidget(parent, SWT.NONE); - GridData data = new GridData(GridData.FILL_HORIZONTAL); - data.horizontalSpan = 2; - infoWidget.setLayoutData(data); - - Dialog.applyDialogFont(parent); - innerParent.layout(); - - return parent; - - } - - /** - * Create grammar list content. - * - * @param parent - */ - private void createDefinitionsListContent(Composite parent) { - Label description = new Label(parent, SWT.NONE); - description.setText(LanguageConfigurationMessages.LanguageConfigurationPreferencePage_description2); - description.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1)); - Composite tableComposite = new Composite(parent, SWT.NONE); - GridData data = new GridData(GridData.FILL_BOTH); - data.widthHint = 360; - data.heightHint = convertHeightInCharsToPixels(10); - tableComposite.setLayoutData(data); - - TableColumnLayout columnLayout = new TableColumnLayout(); - tableComposite.setLayout(columnLayout); - Table table = new Table(tableComposite, - SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL); - - table.setHeaderVisible(true); - table.setLinesVisible(true); - - GC gc = new GC(getShell()); - gc.setFont(JFaceResources.getDialogFont()); - - ColumnViewerComparator viewerComparator = new ColumnViewerComparator(); - - definitionViewer = new TableViewer(table); - - TableColumn column1 = new TableColumn(table, SWT.NONE); - column1.setText(LanguageConfigurationMessages.LanguageConfigurationPreferencePage_contentType); - int minWidth = computeMinimumColumnWidth(gc, - LanguageConfigurationMessages.LanguageConfigurationPreferencePage_contentType); - columnLayout.setColumnData(column1, new ColumnWeightData(2, minWidth, true)); - column1.addSelectionListener(new ColumnSelectionAdapter(column1, definitionViewer, 0, viewerComparator)); - - TableColumn column2 = new TableColumn(table, SWT.NONE); - column2.setText(LanguageConfigurationMessages.LanguageConfigurationPreferencePage_path); - minWidth = computeMinimumColumnWidth(gc, - LanguageConfigurationMessages.LanguageConfigurationPreferencePage_path); - columnLayout.setColumnData(column2, new ColumnWeightData(2, minWidth, true)); - column2.addSelectionListener(new ColumnSelectionAdapter(column2, definitionViewer, 1, viewerComparator)); - - TableColumn column3 = new TableColumn(table, SWT.NONE); - column3.setText(LanguageConfigurationMessages.LanguageConfigurationPreferencePage_pluginId); - minWidth = computeMinimumColumnWidth(gc, - LanguageConfigurationMessages.LanguageConfigurationPreferencePage_pluginId); - columnLayout.setColumnData(column3, new ColumnWeightData(2, minWidth, true)); - column3.addSelectionListener(new ColumnSelectionAdapter(column3, definitionViewer, 2, viewerComparator)); - - gc.dispose(); - - definitionViewer.setLabelProvider(new LanguageConfigurationLabelProvider()); - definitionViewer.setContentProvider(new LanguageConfigurationContentProvider()); - definitionViewer.setComparator(viewerComparator); - - definitionViewer.addSelectionChangedListener(new ISelectionChangedListener() { - - @Override - public void selectionChanged(SelectionChangedEvent e) { - IStructuredSelection selection = definitionViewer.getStructuredSelection(); - infoWidget.refresh(null, manager); - if (selection.isEmpty()) { - return; - } - ILanguageConfigurationDefinition definition = (ILanguageConfigurationDefinition) (selection) - .getFirstElement(); - // Update button - definitionRemoveButton.setEnabled(definition.getPluginId() == null); - selectDefinition(definition); - } - - private void selectDefinition(ILanguageConfigurationDefinition definition) { - infoWidget.refresh(definition, manager); - } - }); - - // Specify default sorting - table.setSortColumn(column1); - table.setSortDirection(viewerComparator.getDirection()); - - BidiUtils.applyTextDirection(definitionViewer.getControl(), BidiUtils.BTD_DEFAULT); - - Composite buttons = new Composite(parent, SWT.NONE); - buttons.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); - GridLayout layout = new GridLayout(); - layout.marginHeight = 0; - layout.marginWidth = 0; - buttons.setLayout(layout); - - definitionNewButton = new Button(buttons, SWT.PUSH); - definitionNewButton.setText(LanguageConfigurationMessages.LanguageConfigurationPreferencePage_new); - definitionNewButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - definitionNewButton.addListener(SWT.Selection, new Listener() { - - @Override - public void handleEvent(Event e) { - add(); - } - - private void add() { - // Open import wizard for language configurations. - LanguageConfigurationImportWizard wizard = new LanguageConfigurationImportWizard(false); - wizard.setRegistryManager(manager); - WizardDialog dialog = new WizardDialog(getShell(), wizard); - if (dialog.open() == Window.OK) { - ILanguageConfigurationDefinition created = wizard.getCreatedDefinition(); - definitionViewer.refresh(); - definitionViewer.setSelection(new StructuredSelection(created)); - } - } - }); - - definitionRemoveButton = new Button(buttons, SWT.PUSH); - definitionRemoveButton.setText(LanguageConfigurationMessages.LanguageConfigurationPreferencePage_remove); - definitionRemoveButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - definitionRemoveButton.addListener(SWT.Selection, new Listener() { - - @Override - public void handleEvent(Event e) { - remove(); - } - - private void remove() { - Collection definitions = getSelectedUserDefinitions(); - if (!definitions.isEmpty()) { - for (ILanguageConfigurationDefinition definition : definitions) { - manager.unregisterLanguageConfigurationDefinition(definition); - } - definitionViewer.refresh(); - } - } - }); - } - - private int computeMinimumColumnWidth(GC gc, String string) { - return gc.stringExtent(string).x + 10; // pad 10 to accommodate table header trimmings - } - - /** - * Returns list of selected definitions which was created by the user. - * - * @return list of selected definitions which was created by the user. - */ - @SuppressWarnings("unchecked") - private Collection getSelectedUserDefinitions() { - IStructuredSelection selection = definitionViewer.getStructuredSelection(); - if (selection.isEmpty()) { - return Collections.emptyList(); - } - return ((Collection) selection.toList()).stream() - .filter(definition -> definition.getPluginId() == null).collect(Collectors.toList()); - } - - @Override - public void setVisible(boolean visible) { - super.setVisible(visible); - if (visible) { - setTitle(LanguageConfigurationMessages.LanguageConfigurationPreferencePage_title); - } - } - - @Override - public boolean performOk() { - try { - manager.save(); - } catch (BackingStoreException e) { - // TODO: Log - } - return super.performOk(); - } - - @Override - public void init(IWorkbench workbench) { - - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + * Lucas Bullen (Red Hat Inc.) - configuration viewing and editing + */ +package org.eclipse.tm4e.languageconfiguration.internal.preferences; + +import java.util.Collection; +import java.util.Collections; +import java.util.stream.Collectors; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.util.BidiUtils; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationDefinition; +import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationRegistryManager; +import org.eclipse.tm4e.languageconfiguration.WorkingCopyLanguageConfigurationRegistryManager; +import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationMessages; +import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationRegistryManager; +import org.eclipse.tm4e.languageconfiguration.internal.widgets.ColumnSelectionAdapter; +import org.eclipse.tm4e.languageconfiguration.internal.widgets.ColumnViewerComparator; +import org.eclipse.tm4e.languageconfiguration.internal.widgets.LanguageConfigurationPreferencesWidget; +import org.eclipse.tm4e.languageconfiguration.internal.wizards.LanguageConfigurationImportWizard; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.osgi.service.prefs.BackingStoreException; + +/** + * A language configuration preference page allows configuration of the language + * configuration It provides controls for adding, removing and changing language + * configuration as well as enablement, default management. + */ +public final class LanguageConfigurationPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { + + static final String PAGE_ID = "org.eclipse.tm4e.languageconfiguration.preferences.LanguageConfigurationPreferencePage"; //$NON-NLS-1$ + + private final ILanguageConfigurationRegistryManager manager = new WorkingCopyLanguageConfigurationRegistryManager( + LanguageConfigurationRegistryManager.getInstance()); + + @Nullable + private TableViewer definitionViewer; + + @Nullable + private LanguageConfigurationPreferencesWidget infoWidget; + + public LanguageConfigurationPreferencePage() { + setDescription(LanguageConfigurationMessages.LanguageConfigurationPreferencePage_description); + } + + @Override + protected Control createContents(@Nullable final Composite ancestor) { + final var parent = new Composite(ancestor, SWT.NONE); + final var layout = new GridLayout(); + layout.numColumns = 2; + layout.marginHeight = 0; + layout.marginWidth = 0; + parent.setLayout(layout); + + final var innerParent = new Composite(parent, SWT.NONE); + final var innerLayout = new GridLayout(); + innerLayout.numColumns = 2; + innerLayout.marginHeight = 0; + innerLayout.marginWidth = 0; + innerParent.setLayout(innerLayout); + final var gd = new GridData(GridData.FILL_BOTH); + gd.horizontalSpan = 2; + innerParent.setLayoutData(gd); + + createDefinitionsListContent(parent); + + assert definitionViewer != null; + definitionViewer.setInput(manager); + + final var infoWidget = new LanguageConfigurationPreferencesWidget(parent, SWT.NONE); + this.infoWidget = infoWidget; + + final var data = new GridData(GridData.FILL_HORIZONTAL); + data.horizontalSpan = 2; + infoWidget.setLayoutData(data); + + Dialog.applyDialogFont(parent); + innerParent.layout(); + + return parent; + + } + + /** + * Create grammar list content. + * + * @param parent + */ + private void createDefinitionsListContent(final Composite parent) { + final var description = new Label(parent, SWT.NONE); + description.setText(LanguageConfigurationMessages.LanguageConfigurationPreferencePage_description2); + description.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1)); + final var tableComposite = new Composite(parent, SWT.NONE); + final var data = new GridData(GridData.FILL_BOTH); + data.widthHint = 360; + data.heightHint = convertHeightInCharsToPixels(10); + tableComposite.setLayoutData(data); + + final var columnLayout = new TableColumnLayout(); + tableComposite.setLayout(columnLayout); + final var table = new Table(tableComposite, + SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL); + + table.setHeaderVisible(true); + table.setLinesVisible(true); + + final GC gc = new GC(getShell()); + gc.setFont(JFaceResources.getDialogFont()); + + final var viewerComparator = new ColumnViewerComparator(); + + final var definitionViewer = new TableViewer(table); + this.definitionViewer = definitionViewer; + + final var column1 = new TableColumn(table, SWT.NONE); + column1.setText(LanguageConfigurationMessages.LanguageConfigurationPreferencePage_contentType); + int minWidth = computeMinimumColumnWidth(gc, + LanguageConfigurationMessages.LanguageConfigurationPreferencePage_contentType); + columnLayout.setColumnData(column1, new ColumnWeightData(2, minWidth, true)); + column1.addSelectionListener(new ColumnSelectionAdapter(column1, definitionViewer, 0, viewerComparator)); + + final var column2 = new TableColumn(table, SWT.NONE); + column2.setText(LanguageConfigurationMessages.LanguageConfigurationPreferencePage_path); + minWidth = computeMinimumColumnWidth(gc, + LanguageConfigurationMessages.LanguageConfigurationPreferencePage_path); + columnLayout.setColumnData(column2, new ColumnWeightData(2, minWidth, true)); + column2.addSelectionListener(new ColumnSelectionAdapter(column2, definitionViewer, 1, viewerComparator)); + + final var column3 = new TableColumn(table, SWT.NONE); + column3.setText(LanguageConfigurationMessages.LanguageConfigurationPreferencePage_pluginId); + minWidth = computeMinimumColumnWidth(gc, + LanguageConfigurationMessages.LanguageConfigurationPreferencePage_pluginId); + columnLayout.setColumnData(column3, new ColumnWeightData(2, minWidth, true)); + column3.addSelectionListener(new ColumnSelectionAdapter(column3, definitionViewer, 2, viewerComparator)); + + gc.dispose(); + + definitionViewer.setLabelProvider(new LanguageConfigurationLabelProvider()); + definitionViewer.setContentProvider(new LanguageConfigurationContentProvider()); + definitionViewer.setComparator(viewerComparator); + + // Specify default sorting + table.setSortColumn(column1); + table.setSortDirection(viewerComparator.getDirection()); + + BidiUtils.applyTextDirection(definitionViewer.getControl(), BidiUtils.BTD_DEFAULT); + + final var buttons = new Composite(parent, SWT.NONE); + buttons.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); + final var layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + buttons.setLayout(layout); + + final var definitionNewButton = new Button(buttons, SWT.PUSH); + definitionNewButton.setText(LanguageConfigurationMessages.LanguageConfigurationPreferencePage_new); + definitionNewButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + definitionNewButton.addListener(SWT.Selection, new Listener() { + @Override + public void handleEvent(@Nullable final Event e) { + add(); + } + + private void add() { + // Open import wizard for language configurations. + final var wizard = new LanguageConfigurationImportWizard(false); + wizard.setRegistryManager(manager); + final var dialog = new WizardDialog(getShell(), wizard); + if (dialog.open() == Window.OK) { + final var created = wizard.getCreatedDefinition(); + definitionViewer.refresh(); + definitionViewer.setSelection(new StructuredSelection(created)); + } + } + }); + + final var definitionRemoveButton = new Button(buttons, SWT.PUSH); + definitionRemoveButton.setText(LanguageConfigurationMessages.LanguageConfigurationPreferencePage_remove); + definitionRemoveButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + definitionRemoveButton.addListener(SWT.Selection, new Listener() { + @Override + public void handleEvent(@Nullable final Event e) { + remove(); + } + + private void remove() { + final var definitions = getSelectedUserDefinitions(definitionViewer); + if (!definitions.isEmpty()) { + for (final var definition : definitions) { + manager.unregisterLanguageConfigurationDefinition(definition); + } + definitionViewer.refresh(); + } + } + }); + + definitionViewer.addSelectionChangedListener(new ISelectionChangedListener() { + @Override + public void selectionChanged(@Nullable final SelectionChangedEvent e) { + final var selection = definitionViewer.getStructuredSelection(); + assert infoWidget != null; + infoWidget.refresh(null, manager); + if (selection.isEmpty()) { + return; + } + final var definition = (ILanguageConfigurationDefinition) (selection).getFirstElement(); + // Update button + assert definitionRemoveButton != null; + definitionRemoveButton.setEnabled(definition.getPluginId() == null); + selectDefinition(definition); + } + + private void selectDefinition(final ILanguageConfigurationDefinition definition) { + assert infoWidget != null; + infoWidget.refresh(definition, manager); + } + }); + } + + private int computeMinimumColumnWidth(final GC gc, final String string) { + return gc.stringExtent(string).x + 10; // pad 10 to accommodate table header trimmings + } + + /** + * Returns list of selected definitions which was created by the user. + * + * @return list of selected definitions which was created by the user. + */ + private Collection getSelectedUserDefinitions( + final TableViewer definitionViewer) { + final var selection = definitionViewer.getStructuredSelection(); + if (selection.isEmpty()) { + return Collections.emptyList(); + } + return ((Collection) selection.toList()).stream() + .filter(definition -> definition.getPluginId() == null).collect(Collectors.toList()); + } + + @Override + public void setVisible(final boolean visible) { + super.setVisible(visible); + if (visible) { + setTitle(LanguageConfigurationMessages.LanguageConfigurationPreferencePage_title); + } + } + + @Override + public boolean performOk() { + try { + manager.save(); + } catch (final BackingStoreException e) { + // TODO: Log + } + return super.performOk(); + } + + @Override + public void init(@Nullable final IWorkbench workbench) { + + } +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/PreferenceConstants.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/PreferenceConstants.java index ecad6d1eb..9e29e4d25 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/PreferenceConstants.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/PreferenceConstants.java @@ -1,22 +1,22 @@ -/** - * Copyright (c) 2018 Red Hat Inc. and others. +/** + * Copyright (c) 2018 Red Hat Inc. and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Lucas Bullen (Red Hat Inc.) - initial API and implementation - */ -package org.eclipse.tm4e.languageconfiguration.internal.preferences; - -/** - * Preferences constants for language configurations. - * - */ -public class PreferenceConstants { - - public static final String LANGUAGE_CONFIGURATIONS = "org.eclipse.tm4e.languageConfigurations"; //$NON-NLS-1$ - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Lucas Bullen (Red Hat Inc.) - initial API and implementation + */ +package org.eclipse.tm4e.languageconfiguration.internal.preferences; + +/** + * Preferences constants for language configurations. + * + */ +public final class PreferenceConstants { + + public static final String LANGUAGE_CONFIGURATIONS = "org.eclipse.tm4e.languageConfigurations"; //$NON-NLS-1$ + +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/PreferenceHelper.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/PreferenceHelper.java index 90e1f22f2..e39b022ab 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/PreferenceHelper.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/PreferenceHelper.java @@ -1,69 +1,80 @@ -/** - * Copyright (c) 2018 Red Hat Inc. and others. +/** + * Copyright (c) 2018 Red Hat Inc. and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Lucas Bullen (Red Hat Inc.) - initial API and implementation - */ -package org.eclipse.tm4e.languageconfiguration.internal.preferences; - -import java.util.Collection; - -import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationDefinition; -import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationDefinition; -import org.eclipse.tm4e.ui.utils.ContentTypeHelper; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonSerializer; - -/** - * Helper class load, save language configuration preferences with Json format. - * - */ -public class PreferenceHelper { - - private static final Gson DEFAULT_GSON; - - static { - DEFAULT_GSON = new GsonBuilder().registerTypeAdapter(LanguageConfigurationDefinition.class, - (JsonDeserializer) (json, typeOfT, context) -> { - JsonObject object = json.getAsJsonObject(); - JsonElement pluginId = object.get("pluginId"); - return new LanguageConfigurationDefinition( - ContentTypeHelper.getContentTypeById(object.get("contentTypeId").getAsString()), //$NON-NLS-1$ - object.get("path").getAsString(), //$NON-NLS-1$ - pluginId == null ? null : pluginId.getAsString(), - object.get("onEnterEnabled").getAsBoolean(), //$NON-NLS-1$ - object.get("bracketAutoClosingEnabled").getAsBoolean(), //$NON-NLS-1$ - object.get("matchingPairsEnabled").getAsBoolean()); //$NON-NLS-1$ - }).registerTypeAdapter(LanguageConfigurationDefinition.class, - (JsonSerializer) (definition, typeOfT, context) -> { - JsonObject object = new JsonObject(); - object.addProperty("path", definition.getPath()); //$NON-NLS-1$ - object.addProperty("pluginId", definition.getPluginId()); //$NON-NLS-1$ - object.addProperty("contentTypeId", definition.getContentType().getId()); //$NON-NLS-1$ - object.addProperty("onEnterEnabled", definition.isOnEnterEnabled()); //$NON-NLS-1$ - object.addProperty("bracketAutoClosingEnabled", definition.isBracketAutoClosingEnabled()); //$NON-NLS-1$ - object.addProperty("matchingPairsEnabled", definition.isMatchingPairsEnabled()); //$NON-NLS-1$ - return object; - }) - .create(); - } - - public static ILanguageConfigurationDefinition[] loadLanguageConfigurationDefinitions(String json) { - return DEFAULT_GSON.fromJson(json, LanguageConfigurationDefinition[].class); - } - - public static String toJson(Collection definitions) { - return DEFAULT_GSON.toJson(definitions); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Lucas Bullen (Red Hat Inc.) - initial API and implementation + */ +package org.eclipse.tm4e.languageconfiguration.internal.preferences; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Objects; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationDefinition; +import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationDefinition; +import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationPlugin; +import org.eclipse.tm4e.ui.internal.utils.ContentTypeHelper; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializer; + +/** + * Helper class load, save language configuration preferences with Json format. + */ +public final class PreferenceHelper { + + private static final Gson DEFAULT_GSON = new GsonBuilder() + .registerTypeAdapter(LanguageConfigurationDefinition.class, + (JsonDeserializer<@Nullable LanguageConfigurationDefinition>) (json, typeOfT, context) -> { + final JsonObject object = json.getAsJsonObject(); + final JsonElement pluginId = object.get("pluginId"); + final var contentTypeId = object.get("contentTypeId").getAsString(); + final var contentType = ContentTypeHelper.getContentTypeById(contentTypeId); + if (contentType == null) { + LanguageConfigurationPlugin.log(new Status(IStatus.ERROR, PreferenceHelper.class, + "Cannot load language configuration with unknown content type ID " + + contentTypeId)); + return null; + } + return new LanguageConfigurationDefinition(contentType, // $NON-NLS-1$ + object.get("path").getAsString(), //$NON-NLS-1$ + pluginId == null ? null : pluginId.getAsString(), + object.get("onEnterEnabled").getAsBoolean(), //$NON-NLS-1$ + object.get("bracketAutoClosingEnabled").getAsBoolean(), //$NON-NLS-1$ + object.get("matchingPairsEnabled").getAsBoolean()); //$NON-NLS-1$ + }) + .registerTypeAdapter(LanguageConfigurationDefinition.class, + (JsonSerializer) (definition, typeOfT, context) -> { + final JsonObject object = new JsonObject(); + object.addProperty("path", definition.getPath()); //$NON-NLS-1$ + object.addProperty("pluginId", definition.getPluginId()); //$NON-NLS-1$ + object.addProperty("contentTypeId", definition.getContentType().getId()); //$NON-NLS-1$ + object.addProperty("onEnterEnabled", definition.isOnEnterEnabled()); //$NON-NLS-1$ + object.addProperty("bracketAutoClosingEnabled", definition.isBracketAutoClosingEnabled()); //$NON-NLS-1$ + object.addProperty("matchingPairsEnabled", definition.isMatchingPairsEnabled()); //$NON-NLS-1$ + return object; + }) + .create(); + + public static ILanguageConfigurationDefinition[] loadLanguageConfigurationDefinitions(final String json) { + return Arrays.stream(DEFAULT_GSON.fromJson(json, LanguageConfigurationDefinition[].class)) + .filter(Objects::nonNull).toArray( + ILanguageConfigurationDefinition[]::new); + } + + public static String toJson(final Collection definitions) { + return DEFAULT_GSON.toJson(definitions); + } +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/package-info.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/package-info.java new file mode 100644 index 000000000..eaea04298 --- /dev/null +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/preferences/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.languageconfiguration.internal.preferences; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/AutoClosingPairConditional.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/AutoClosingPairConditional.java index fdfb35e98..eeb849d9d 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/AutoClosingPairConditional.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/AutoClosingPairConditional.java @@ -9,21 +9,25 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.languageconfiguration.internal.supports; - -import java.util.List; - -@SuppressWarnings("serial") -public class AutoClosingPairConditional extends CharacterPair { - - private List notIn; - - public AutoClosingPairConditional(String open, String close, List notIn) { - super(open, close); - this.notIn = notIn; - } - - public List getNotIn() { - return notIn; - } -} +package org.eclipse.tm4e.languageconfiguration.internal.supports; + +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; + +@SuppressWarnings("serial") +public final class AutoClosingPairConditional extends CharacterPair { + + @Nullable + private final List notIn; + + public AutoClosingPairConditional(final String open, final String close, @Nullable final List notIn) { + super(open, close); + this.notIn = notIn; + } + + @Nullable + public List getNotIn() { + return notIn; + } +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/CharacterPair.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/CharacterPair.java index 28c3f536a..d29f623f9 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/CharacterPair.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/CharacterPair.java @@ -1,26 +1,26 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.languageconfiguration.internal.supports; - -import java.util.AbstractMap.SimpleEntry; - -/** - * A tuple of two characters, like a pair of opening and closing brackets. - */ -@SuppressWarnings("serial") -public class CharacterPair extends SimpleEntry { - - public CharacterPair(String key, String value) { - super(key, value); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.languageconfiguration.internal.supports; + +import java.util.AbstractMap.SimpleEntry; + +/** + * A tuple of two characters, like a pair of opening and closing brackets. + */ +public class CharacterPair extends SimpleEntry { + + private static final long serialVersionUID = 1L; + + public CharacterPair(final String key, final String value) { + super(key, value); + } +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/CharacterPairSupport.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/CharacterPairSupport.java index 10ec3eb8f..c2f9c3cf5 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/CharacterPairSupport.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/CharacterPairSupport.java @@ -1,74 +1,78 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.languageconfiguration.internal.supports; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * The "character pair" support. - * - */ -public class CharacterPairSupport { - - private List autoClosingPairs; - private List surroundingPairs; - - public CharacterPairSupport(List brackets, List autoClosingPairs, - List surroundingPairs) { - if (autoClosingPairs != null) { - this.autoClosingPairs = autoClosingPairs.stream().filter(el -> el != null) - .map(el -> new AutoClosingPairConditional(el.getKey(), el.getValue(), el.getNotIn())) - .collect(Collectors.toList()); - } else if (brackets != null) { - this.autoClosingPairs = brackets.stream().filter(el -> el != null) - .map(el -> new AutoClosingPairConditional(el.getKey(), el.getValue(), null)) - .collect(Collectors.toList()); - } else { - this.autoClosingPairs = new ArrayList<>(); - } - - this.surroundingPairs = surroundingPairs != null - ? surroundingPairs.stream().filter(el -> el != null).collect(Collectors.toList()) - : this.autoClosingPairs; - } - - public CharacterPair getAutoClosePair(String text, Integer offset, - String newCharacter/* : string, context: ScopedLineTokens, column: number */) { - if (newCharacter.isEmpty()) { - return null; - } - for (CharacterPair autoClosingPair : autoClosingPairs) { - String openning = autoClosingPair.getKey(); - if (!openning.endsWith(newCharacter)) { - continue; - } - if (openning.length() > 1) { - String offsetPrefix = text.substring(0, offset); - if (!offsetPrefix.endsWith(openning.substring(0, openning.length() - 1))) { - continue; - } - } - return autoClosingPair; - } - return null; - } - - public List getAutoClosingPairs() { - return autoClosingPairs; - } - - public List getSurroundingPairs() { - return surroundingPairs; - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.languageconfiguration.internal.supports; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * The "character pair" support. + */ +public final class CharacterPairSupport { + + private List autoClosingPairs; + private final List surroundingPairs; + + public CharacterPairSupport(@Nullable final List brackets, + @Nullable final List autoClosingPairs, + @Nullable final List surroundingPairs) { + if (autoClosingPairs != null) { + this.autoClosingPairs = autoClosingPairs.stream().filter(Objects::nonNull) + .map(el -> new AutoClosingPairConditional(el.getKey(), el.getValue(), el.getNotIn())) + .collect(Collectors.toList()); + } else if (brackets != null) { + this.autoClosingPairs = brackets.stream().filter(Objects::nonNull) + .map(el -> new AutoClosingPairConditional(el.getKey(), el.getValue(), null)) + .collect(Collectors.toList()); + } else { + this.autoClosingPairs = new ArrayList<>(); + } + + this.surroundingPairs = surroundingPairs != null + ? surroundingPairs.stream().filter(Objects::nonNull).collect(Collectors.toList()) + : this.autoClosingPairs; + } + + @Nullable + public CharacterPair getAutoClosePair(final String text, final int offset, + final String newCharacter/* : string, context: ScopedLineTokens, column: number */) { + if (newCharacter.isEmpty()) { + return null; + } + for (final CharacterPair autoClosingPair : autoClosingPairs) { + final String opening = autoClosingPair.getKey(); + if (!opening.endsWith(newCharacter)) { + continue; + } + if (opening.length() > 1) { + final String offsetPrefix = text.substring(0, offset); + if (!offsetPrefix.endsWith(opening.substring(0, opening.length() - 1))) { + continue; + } + } + return autoClosingPair; + } + return null; + } + + public List getAutoClosingPairs() { + return autoClosingPairs; + } + + public List getSurroundingPairs() { + return surroundingPairs; + } +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/CommentSupport.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/CommentSupport.java index 3c83bd1c4..bfce90cb9 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/CommentSupport.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/CommentSupport.java @@ -1,58 +1,75 @@ /** - * Copyright (c) 2018 Red Hat Inc. and others. + * Copyright (c) 2018 Red Hat Inc. and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * - * Contributors: - * Lucas Bullen (Red Hat Inc.) - initial API and implementation + * Contributors: + * Lucas Bullen (Red Hat Inc.) - initial API and implementation */ package org.eclipse.tm4e.languageconfiguration.internal.supports; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; -public class CommentSupport { +public final class CommentSupport { - private Comments comments; + @Nullable + private final Comments comments; - public CommentSupport(Comments comments) { + public CommentSupport(@Nullable final Comments comments) { this.comments = comments; } - public boolean isInComment(IDocument document, int offset) { + private boolean isInComment(final IDocument document, final int offset) { try { if (isInBlockComment(document.get(0, offset))) { return true; } - int line = document.getLineOfOffset(offset); - int lineOffset = document.getLineOffset(line); + final int line = document.getLineOfOffset(offset); + final int lineOffset = document.getLineOffset(line); return isInLineComment(document.get(lineOffset, offset - lineOffset)); - } catch (BadLocationException e) { + } catch (final BadLocationException e) { return false; } } + @Nullable public String getLineComment() { - return comments.getLineComment(); + final var comments = this.comments; + return comments == null ? null : comments.getLineComment(); } + @Nullable public CharacterPair getBlockComment() { - return comments.getBlockComment(); + final var comments = this.comments; + return comments == null ? null : comments.getBlockComment(); } - private boolean isInLineComment(String indexLinePrefix) { + private boolean isInLineComment(final String indexLinePrefix) { + final var comments = this.comments; + if (comments == null) + return false; return indexLinePrefix.indexOf(comments.getLineComment()) != -1; } - private boolean isInBlockComment(String indexPrefix) { - String commentOpen = comments.getBlockComment().getKey(); - String commentClose = comments.getBlockComment().getValue(); + private boolean isInBlockComment(final String indexPrefix) { + final var comments = this.comments; + if (comments == null) + return false; + + final var blockComment = comments.getBlockComment(); + if (blockComment == null) + return false; + + final String commentOpen = blockComment.getKey(); + final String commentClose = blockComment.getValue(); int index = indexPrefix.indexOf(commentOpen); while (index != -1 && index < indexPrefix.length()) { - int closeIndex = indexPrefix.indexOf(commentClose, index + commentOpen.length()); + final int closeIndex = indexPrefix.indexOf(commentClose, index + commentOpen.length()); if (closeIndex == -1) { return true; } diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/Comments.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/Comments.java index ff8490c89..05dd96e42 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/Comments.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/Comments.java @@ -1,31 +1,37 @@ /** - * Copyright (c) 2018 Red Hat Inc. and others. + * Copyright (c) 2018 Red Hat Inc. and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * - * Contributors: - * Lucas Bullen (Red Hat Inc.) - initial API and implementation + * Contributors: + * Lucas Bullen (Red Hat Inc.) - initial API and implementation */ package org.eclipse.tm4e.languageconfiguration.internal.supports; -public class Comments { +import org.eclipse.jdt.annotation.Nullable; +public final class Comments { + + @Nullable private final String lineComment; + @Nullable private final CharacterPair blockComment; - public Comments(String lineComment, CharacterPair blockComment) { + public Comments(@Nullable final String lineComment, @Nullable final CharacterPair blockComment) { this.lineComment = lineComment; this.blockComment = blockComment; } + @Nullable public String getLineComment() { return lineComment; } + @Nullable public CharacterPair getBlockComment() { return blockComment; } diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/EnterAction.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/EnterAction.java index 40bf7ce4b..fdcd4962b 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/EnterAction.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/EnterAction.java @@ -9,110 +9,116 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.languageconfiguration.internal.supports; - -/** - * Describes what to do when pressing Enter. - */ -public class EnterAction { - - public enum IndentAction { - /** - * Insert new line and copy the previous line's indentation. - */ - None, - /** - * Insert new line and indent once (relative to the previous line's - * indentation). - */ - Indent, - /** - * Insert two new lines: - the first one indented which will hold the cursor - - * the second one at the same indentation level - */ - IndentOutdent, - /** - * Insert new line and outdent once (relative to the previous line's - * indentation). - */ - Outdent; - } - - /** - * Describe what to do with the indentation. - */ - private final IndentAction indentAction; - - /** - * Describe whether to outdent current line. - */ - private Boolean outdentCurrentLine; - /** - * Describes text to be appended after the new line and after the indentation. - */ - private String appendText; - /** - * Describes the number of characters to remove from the new line's indentation. - */ - private Integer removeText; - - public EnterAction(IndentAction indentAction) { - this.indentAction = indentAction; - } - - public IndentAction getIndentAction() { - return indentAction; - } - - /** - * @return the outdentCurrentLine - */ - public Boolean getOutdentCurrentLine() { - return outdentCurrentLine; - } - - /** - * @param outdentCurrentLine - * the outdentCurrentLine to set - * @return - */ - public EnterAction setOutdentCurrentLine(Boolean outdentCurrentLine) { - this.outdentCurrentLine = outdentCurrentLine; - return this; - } - - /** - * @return the appendText - */ - public String getAppendText() { - return appendText; - } - - /** - * @param appendText - * the appendText to set - * @return - */ - public EnterAction setAppendText(String appendText) { - this.appendText = appendText; - return this; - } - - /** - * @return the removeText - */ - public Integer getRemoveText() { - return removeText; - } - - /** - * @param removeText - * the removeText to set - * @return - */ - public EnterAction setRemoveText(Integer removeText) { - this.removeText = removeText; - return this; - } - -} +package org.eclipse.tm4e.languageconfiguration.internal.supports; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * Describes what to do when pressing Enter. + */ +public final class EnterAction { + + public enum IndentAction { + /** + * Insert new line and copy the previous line's indentation. + */ + None, + /** + * Insert new line and indent once (relative to the previous line's + * indentation). + */ + Indent, + /** + * Insert two new lines: - the first one indented which will hold the cursor - + * the second one at the same indentation level + */ + IndentOutdent, + /** + * Insert new line and outdent once (relative to the previous line's + * indentation). + */ + Outdent; + } + + /** + * Describe what to do with the indentation. + */ + private final IndentAction indentAction; + + /** + * Describe whether to outdent current line. + */ + @Nullable + private Boolean outdentCurrentLine; + + /** + * Describes text to be appended after the new line and after the indentation. + */ + @Nullable + private String appendText; + + /** + * Describes the number of characters to remove from the new line's indentation. + */ + @Nullable + private Integer removeText; + + public EnterAction(final IndentAction indentAction) { + this.indentAction = indentAction; + } + + public IndentAction getIndentAction() { + return indentAction; + } + + /** + * @return the outdentCurrentLine + */ + @Nullable + private Boolean getOutdentCurrentLine() { + return outdentCurrentLine; + } + + /** + * @param outdentCurrentLine + * the outdentCurrentLine to set + * @return + */ + private EnterAction setOutdentCurrentLine(final Boolean outdentCurrentLine) { + this.outdentCurrentLine = outdentCurrentLine; + return this; + } + + /** + * @return the appendText + */ + @Nullable + public String getAppendText() { + return appendText; + } + + /** + * @param appendText the appendText to set + */ + public EnterAction setAppendText(@Nullable final String appendText) { + this.appendText = appendText; + return this; + } + + /** + * @return the removeText + */ + @Nullable + public Integer getRemoveText() { + return removeText; + } + + /** + * @param removeText the removeText to set + */ + public EnterAction setRemoveText(@Nullable final Integer removeText) { + this.removeText = removeText; + return this; + } + +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/EnterActionAndIndent.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/EnterActionAndIndent.java index b887f2092..bf749358f 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/EnterActionAndIndent.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/EnterActionAndIndent.java @@ -9,29 +9,28 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.languageconfiguration.internal.supports; - -public class EnterActionAndIndent { - - private final EnterAction enterAction; - - private final String indentation; - - /** - * @param enterAction - * @param indentation - */ - public EnterActionAndIndent(EnterAction enterAction, String indentation) { - super(); - this.enterAction = enterAction; - this.indentation = indentation; - } - - public EnterAction getEnterAction() { - return enterAction; - } - - public String getIndentation() { - return indentation; - } -} +package org.eclipse.tm4e.languageconfiguration.internal.supports; + +public final class EnterActionAndIndent { + + private final EnterAction enterAction; + + private final String indentation; + + /** + * @param enterAction + * @param indentation + */ + public EnterActionAndIndent(final EnterAction enterAction, final String indentation) { + this.enterAction = enterAction; + this.indentation = indentation; + } + + public EnterAction getEnterAction() { + return enterAction; + } + + public String getIndentation() { + return indentation; + } +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/Folding.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/Folding.java index 3c2b8818a..ebd34b5bf 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/Folding.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/Folding.java @@ -11,7 +11,7 @@ */ package org.eclipse.tm4e.languageconfiguration.internal.supports; -public class Folding { +public final class Folding { private final Boolean offSide; @@ -19,7 +19,7 @@ public class Folding { private final String markersEnd; - public Folding(Boolean offSide, String markersStart, String markersEnd) { + public Folding(final Boolean offSide, final String markersStart, final String markersEnd) { this.offSide = offSide; this.markersStart = markersStart; this.markersEnd = markersEnd; diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/IndentationRule.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/IndentationRule.java index 740240835..431210e72 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/IndentationRule.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/IndentationRule.java @@ -9,8 +9,11 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.languageconfiguration.internal.supports; - -public class IndentationRule { - -} +package org.eclipse.tm4e.languageconfiguration.internal.supports; + +/** + * TODO unused class + */ +final class IndentationRule { + +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/OnEnterRule.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/OnEnterRule.java index 84c173004..3cd183579 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/OnEnterRule.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/OnEnterRule.java @@ -9,50 +9,53 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.languageconfiguration.internal.supports; - -import java.util.regex.Pattern; - -import org.eclipse.tm4e.languageconfiguration.internal.utils.RegExpUtils; - -/** - * Describes a rule to be evaluated when pressing Enter. - */ -public class OnEnterRule { - - /** - * This rule will only execute if the text before the cursor matches this - * regular expression. - */ - private final Pattern beforeText; - - /** - * This rule will only execute if the text after the cursor matches this regular - * expression. - */ - private final Pattern afterText; - - /** - * The action to execute. - */ - private final EnterAction action; - - public OnEnterRule(String beforeText, String afterText, EnterAction action) { - this.beforeText = RegExpUtils.create(beforeText); - this.afterText = afterText != null ? RegExpUtils.create(afterText) : null; - this.action = action; - } - - public Pattern getBeforeText() { - return beforeText; - } - - public Pattern getAfterText() { - return afterText; - } - - public EnterAction getAction() { - return action; - } - -} +package org.eclipse.tm4e.languageconfiguration.internal.supports; + +import java.util.regex.Pattern; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.languageconfiguration.internal.utils.RegExpUtils; + +/** + * Describes a rule to be evaluated when pressing Enter. + */ +public final class OnEnterRule { + + /** + * This rule will only execute if the text before the cursor matches this regular expression. + */ + @Nullable + private final Pattern beforeText; + + /** + * This rule will only execute if the text after the cursor matches this regular expression. + */ + @Nullable + private final Pattern afterText; + + /** + * The action to execute. + */ + private final EnterAction action; + + public OnEnterRule(final String beforeText, @Nullable final String afterText, final EnterAction action) { + this.beforeText = RegExpUtils.create(beforeText); + this.afterText = afterText != null ? RegExpUtils.create(afterText) : null; + this.action = action; + } + + @Nullable + public Pattern getBeforeText() { + return beforeText; + } + + @Nullable + public Pattern getAfterText() { + return afterText; + } + + public EnterAction getAction() { + return action; + } + +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/OnEnterSupport.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/OnEnterSupport.java index 050f8332c..1c792971f 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/OnEnterSupport.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/OnEnterSupport.java @@ -1,120 +1,130 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.languageconfiguration.internal.supports; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import org.eclipse.tm4e.languageconfiguration.internal.supports.EnterAction.IndentAction; -import org.eclipse.tm4e.languageconfiguration.internal.utils.RegExpUtils; - -/** - * On enter support. - * - */ -public class OnEnterSupport { - - private static final List DEFAULT_BRACKETS = Arrays.asList(new CharacterPair("(", ")"), //$NON-NLS-1$ //$NON-NLS-2$ - new CharacterPair("{", "}"), new CharacterPair("[", "]")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - - private final List brackets; - - private final List regExpRules; - - public OnEnterSupport(List brackets, List regExpRules) { - this.brackets = (brackets != null ? brackets : DEFAULT_BRACKETS).stream().filter(el -> el != null) - .map((bracket -> { - return new ProcessedBracketPair(bracket.getKey(), bracket.getValue()); - })).collect(Collectors.toList()); - - this.regExpRules = regExpRules != null ? regExpRules : Collections.emptyList(); - } - - public EnterAction onEnter(String oneLineAboveText, String beforeEnterText, String afterEnterText) { - // (1): `regExpRules` - for (OnEnterRule rule : regExpRules) { - if (rule.getBeforeText().matcher(beforeEnterText).find()) { - if (rule.getAfterText() != null) { - if (rule.getAfterText().matcher(afterEnterText).find()) { - return rule.getAction(); - } - } else { - return rule.getAction(); - } - } - } - - // (2): Special indent-outdent - if (beforeEnterText.length() > 0 && afterEnterText.length() > 0) { - for (ProcessedBracketPair bracket : brackets) { - if (bracket.matchOpen(beforeEnterText) && bracket.matchClose(afterEnterText)) { - return new EnterAction(IndentAction.IndentOutdent); - } - } - } - - // (3): Open bracket based logic - if (beforeEnterText.length() > 0) { - for (ProcessedBracketPair bracket : brackets) { - if (bracket.matchOpen(beforeEnterText)) { - return new EnterAction(IndentAction.Indent); - } - } - } - return null; - } - - private static class ProcessedBracketPair { - - private static final Pattern B_REGEXP = Pattern.compile("\\B"); //$NON-NLS-1$ - - private final Pattern openRegExp; - private final Pattern closeRegExp; - - public ProcessedBracketPair(String open, String close) { - openRegExp = createOpenBracketRegExp(open); - closeRegExp = createCloseBracketRegExp(close); - } - - public boolean matchOpen(String beforeEnterText) { - return openRegExp != null && openRegExp.matcher(beforeEnterText).find(); - } - - public boolean matchClose(String afterEnterText) { - return closeRegExp != null && closeRegExp.matcher(afterEnterText).find(); - } - - private static Pattern createOpenBracketRegExp(String bracket) { - StringBuilder str = new StringBuilder(RegExpUtils.escapeRegExpCharacters(bracket)); - String c = String.valueOf(str.charAt(0)); - if (!B_REGEXP.matcher(c).find()) { - str.insert(0, "\\b"); //$NON-NLS-1$ - } - str.append("\\s*$"); //$NON-NLS-1$ - return RegExpUtils.create(str.toString()); - } - - private static Pattern createCloseBracketRegExp(String bracket) { - StringBuilder str = new StringBuilder(RegExpUtils.escapeRegExpCharacters(bracket)); - String c = String.valueOf(str.charAt(str.length() - 1)); - if (!B_REGEXP.matcher(c).find()) { - str.append("\\b"); //$NON-NLS-1$ - } - str.insert(0, "^\\s*"); //$NON-NLS-1$ - return RegExpUtils.create(str.toString()); - } - - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.languageconfiguration.internal.supports; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.languageconfiguration.internal.supports.EnterAction.IndentAction; +import org.eclipse.tm4e.languageconfiguration.internal.utils.RegExpUtils; + +/** + * On enter support. + * + */ +public class OnEnterSupport { + + private static final List DEFAULT_BRACKETS = Arrays.asList( + new CharacterPair("(", ")"), //$NON-NLS-1$ //$NON-NLS-2$ + new CharacterPair("{", "}"), //$NON-NLS-1$ //$NON-NLS-2$ + new CharacterPair("[", "]")); //$NON-NLS-1$ //$NON-NLS-2$ + + private final List brackets; + + private final List regExpRules; + + public OnEnterSupport(@Nullable final List brackets, @Nullable final List regExpRules) { + this.brackets = (brackets != null ? brackets : DEFAULT_BRACKETS).stream().filter(Objects::nonNull) + .map(ProcessedBracketPair::new).collect(Collectors.toList()); + + this.regExpRules = regExpRules != null ? regExpRules : Collections.emptyList(); + } + + @Nullable + public EnterAction onEnter(final String oneLineAboveText, final String beforeEnterText, + final String afterEnterText) { + // (1): `regExpRules` + for (final OnEnterRule rule : regExpRules) { + final var beforeText = rule.getBeforeText(); + if (beforeText != null && beforeText.matcher(beforeEnterText).find()) { + final var afterText = rule.getAfterText(); + if (afterText != null) { + if (afterText.matcher(afterEnterText).find()) { + return rule.getAction(); + } + } else { + return rule.getAction(); + } + } + } + + // (2): Special indent-outdent + if (!beforeEnterText.isEmpty() && !afterEnterText.isEmpty()) { + for (final ProcessedBracketPair bracket : brackets) { + if (bracket.matchOpen(beforeEnterText) && bracket.matchClose(afterEnterText)) { + return new EnterAction(IndentAction.IndentOutdent); + } + } + } + + // (3): Open bracket based logic + if (!beforeEnterText.isEmpty()) { + for (final ProcessedBracketPair bracket : brackets) { + if (bracket.matchOpen(beforeEnterText)) { + return new EnterAction(IndentAction.Indent); + } + } + } + return null; + } + + private static final class ProcessedBracketPair { + + private static final Pattern B_REGEXP = Pattern.compile("\\B"); //$NON-NLS-1$ + + @Nullable + private final Pattern openRegExp; + + @Nullable + private final Pattern closeRegExp; + + private ProcessedBracketPair(final CharacterPair charPair) { + openRegExp = createOpenBracketRegExp(charPair.getKey()); + closeRegExp = createCloseBracketRegExp(charPair.getValue()); + } + + private boolean matchOpen(final String beforeEnterText) { + return openRegExp != null && openRegExp.matcher(beforeEnterText).find(); + } + + private boolean matchClose(final String afterEnterText) { + return closeRegExp != null && closeRegExp.matcher(afterEnterText).find(); + } + + @Nullable + private static Pattern createOpenBracketRegExp(final String bracket) { + final StringBuilder str = new StringBuilder(RegExpUtils.escapeRegExpCharacters(bracket)); + final String c = String.valueOf(str.charAt(0)); + if (!B_REGEXP.matcher(c).find()) { + str.insert(0, "\\b"); //$NON-NLS-1$ + } + str.append("\\s*$"); //$NON-NLS-1$ + return RegExpUtils.create(str.toString()); + } + + @Nullable + private static Pattern createCloseBracketRegExp(final String bracket) { + final StringBuilder str = new StringBuilder(RegExpUtils.escapeRegExpCharacters(bracket)); + final String c = String.valueOf(str.charAt(str.length() - 1)); + if (!B_REGEXP.matcher(c).find()) { + str.append("\\b"); //$NON-NLS-1$ + } + str.insert(0, "^\\s*"); //$NON-NLS-1$ + return RegExpUtils.create(str.toString()); + } + } +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/package-info.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/package-info.java new file mode 100644 index 000000000..f327f6bb4 --- /dev/null +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/supports/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.languageconfiguration.internal.supports; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/utils/RegExpUtils.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/utils/RegExpUtils.java index 4da6d5791..82d4e9823 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/utils/RegExpUtils.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/utils/RegExpUtils.java @@ -1,42 +1,43 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.languageconfiguration.internal.utils; - -import java.util.regex.Pattern; - -/** - * Regex utilities. - * - */ -public class RegExpUtils { - - /** - * Escapes regular expression characters in a given string - */ - public static String escapeRegExpCharacters(String value) { - return value.replaceAll("[\\-\\\\\\{\\}\\*\\+\\?\\|\\^\\$\\.\\[\\]\\(\\)\\#]", "\\\\$0"); //$NON-NLS-1$ //$NON-NLS-2$ - } - - /** - * Create Java Regexp and null otherwise. - * - * @param regex - * @return Java Regexp and null otherwise. - */ - public static Pattern create(String regex) { - try { - return Pattern.compile(regex); - } catch (Exception e) { - return null; - } - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.languageconfiguration.internal.utils; + +import java.util.regex.Pattern; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * Regex utilities. + */ +public final class RegExpUtils { + + /** + * Escapes regular expression characters in a given string + */ + public static String escapeRegExpCharacters(final String value) { + return value.replaceAll("[\\-\\\\\\{\\}\\*\\+\\?\\|\\^\\$\\.\\[\\]\\(\\)\\#]", "\\\\$0"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /** + * Create Java Regexp and null otherwise. + * + * @return Java Regexp and null otherwise. + */ + @Nullable + public static Pattern create(final String regex) { + try { + return Pattern.compile(regex); + } catch (final Exception e) { + return null; + } + } +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/utils/TabSpacesInfo.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/utils/TabSpacesInfo.java index 3af880844..6870f1fde 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/utils/TabSpacesInfo.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/utils/TabSpacesInfo.java @@ -9,23 +9,23 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.languageconfiguration.internal.utils; - -public class TabSpacesInfo { - - private final int tabSize; - private final boolean insertSpaces; - - public TabSpacesInfo(int tabSize, boolean insertSpaces) { - this.tabSize = tabSize; - this.insertSpaces = insertSpaces; - } - - public int getTabSize() { - return tabSize; - } - - public boolean isInsertSpaces() { - return insertSpaces; - } -} +package org.eclipse.tm4e.languageconfiguration.internal.utils; + +public final class TabSpacesInfo { + + private final int tabSize; + private final boolean insertSpaces; + + TabSpacesInfo(final int tabSize, final boolean insertSpaces) { + this.tabSize = tabSize; + this.insertSpaces = insertSpaces; + } + + public int getTabSize() { + return tabSize; + } + + public boolean isInsertSpaces() { + return insertSpaces; + } +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/utils/TextUtils.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/utils/TextUtils.java index bdb536b42..c67c44f2d 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/utils/TextUtils.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/utils/TextUtils.java @@ -1,181 +1,185 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.languageconfiguration.internal.utils; - -import java.util.Arrays; - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.DocumentCommand; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.ITextViewer; -import org.eclipse.jface.text.TabsToSpacesConverter; -import org.eclipse.jface.text.TextUtilities; -import org.eclipse.jface.text.TextViewer; -import org.eclipse.tm4e.ui.utils.ClassHelper; - -public class TextUtils { - - /** - * Returns true if text of the command is an enter and false otherwise. - * - * @param d - * @param c - * @return true if text of the command is an enter and false otherwise. - */ - public static boolean isEnter(IDocument d, DocumentCommand c) { - return (c.length == 0 && c.text != null && TextUtilities.equals(d.getLegalLineDelimiters(), c.text) != -1); - } - - public static String normalizeIndentation(String str, int tabSize, boolean insertSpaces) { - int firstNonWhitespaceIndex = TextUtils.firstNonWhitespaceIndex(str); - if (firstNonWhitespaceIndex == -1) { - firstNonWhitespaceIndex = str.length(); - } - return TextUtils.normalizeIndentationFromWhitespace(str.substring(0, firstNonWhitespaceIndex), tabSize, - insertSpaces) + str.substring(firstNonWhitespaceIndex); - } - - private static String normalizeIndentationFromWhitespace(String str, int tabSize, boolean insertSpaces) { - int spacesCnt = 0; - for (int i = 0; i < str.length(); i++) { - if (str.charAt(i) == '\t') { - spacesCnt += tabSize; - } else { - spacesCnt++; - } - } - - StringBuilder result = new StringBuilder(); - if (!insertSpaces) { - long tabsCnt = Math.round(Math.floor(spacesCnt / tabSize)); - spacesCnt = spacesCnt % tabSize; - for (int i = 0; i < tabsCnt; i++) { - result.append('\t'); - } - } - - for (int i = 0; i < spacesCnt; i++) { - result.append(' '); - } - - return result.toString(); - } - - /** - * Returns the start of the string at the offset in the text. If the string is - * not in the text at the offset, returns -1.
    - * Ex:
    - * text = "apple banana", offset=8, string="banana" returns=6 - */ - public static int startIndexOfOffsetTouchingString(String text, int offset, String string) { - int start = offset - string.length(); - start = start < 0 ? 0 : start; - int end = offset + string.length(); - end = end >= text.length() ? text.length() : end; - try { - int indexInSubtext = text.substring(start, end).indexOf(string); - return indexInSubtext == -1 ? -1 : start + indexInSubtext; - } catch (IndexOutOfBoundsException e) { - return -1; - } - } - - /** - * Returns first index of the string that is not whitespace. If string is empty - * or contains only whitespaces, returns -1 - */ - public static int firstNonWhitespaceIndex(String str) { - for (int i = 0, len = str.length(); i < len; i++) { - char c = str.charAt(i); - if (c != ' ' && c != '\t') { - return i; - } - } - return -1; - } - - public static String getIndentationFromWhitespace(String whitespace, TabSpacesInfo tabSpaces) { - String tab = "\t"; //$NON-NLS-1$ - String spaces = null; - int indentOffset = 0; - boolean startsWithTab = true; - boolean startsWithSpaces = true; - if (tabSpaces.isInsertSpaces()) { - char[] chars = new char[tabSpaces.getTabSize()]; - Arrays.fill(chars, ' '); - spaces = new String(chars); - } - while (startsWithTab || startsWithSpaces) { - startsWithTab = whitespace.startsWith(tab, indentOffset); - startsWithSpaces = tabSpaces.isInsertSpaces() && whitespace.startsWith(spaces, indentOffset); - if (startsWithTab) { - indentOffset += tab.length(); - } - if (startsWithSpaces) { - indentOffset += spaces.length(); - } - } - return whitespace.substring(0, indentOffset); - } - - public static String getLinePrefixingWhitespaceAtPosition(IDocument d, int offset) { - try { - // find start of line - int p = offset; - IRegion info = d.getLineInformationOfOffset(p); - int start = info.getOffset(); - - // find white spaces - int end = findEndOfWhiteSpace(d, start, offset); - - return d.get(start, end - start); - } catch (BadLocationException excp) { - // stop work - } - return ""; //$NON-NLS-1$ - } - - /** - * Returns the first offset greater than offset and smaller than - * end whose character is not a space or tab character. If no such - * offset is found, end is returned. - * - * @param document the document to search in - * @param offset the offset at which searching start - * @param end the offset at which searching stops - * @return the offset in the specified range whose character is not a space or - * tab - * @exception BadLocationException if position is an invalid range in the given - * document - */ - private static int findEndOfWhiteSpace(IDocument document, int offset, int end) throws BadLocationException { - while (offset < end) { - char c = document.getChar(offset); - if (c != ' ' && c != '\t') { - return offset; - } - offset++; - } - return end; - } - - public static TabSpacesInfo getTabSpaces(ITextViewer viewer) { - TabsToSpacesConverter converter = ClassHelper.getFieldValue(viewer, "fTabsToSpacesConverter", TextViewer.class); //$NON-NLS-1$ - if (converter != null) { - int tabSize = ClassHelper.getFieldValue(converter, "fTabRatio", TabsToSpacesConverter.class); //$NON-NLS-1$ - return new TabSpacesInfo(tabSize, true); - } - return new TabSpacesInfo(-1, false); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.languageconfiguration.internal.utils; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DocumentCommand; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.TabsToSpacesConverter; +import org.eclipse.jface.text.TextUtilities; +import org.eclipse.jface.text.TextViewer; +import org.eclipse.tm4e.ui.internal.utils.ClassHelper; + +public final class TextUtils { + + /** + * Returns true if text of the command is an enter and false otherwise. + * + * @param d + * @param c + * + * @return true if text of the command is an enter and false otherwise. + */ + public static boolean isEnter(final IDocument d, final DocumentCommand c) { + return (c.length == 0 && c.text != null && TextUtilities.equals(d.getLegalLineDelimiters(), c.text) != -1); + } + + public static String normalizeIndentation(final String str, final int tabSize, final boolean insertSpaces) { + int firstNonWhitespaceIndex = TextUtils.firstNonWhitespaceIndex(str); + if (firstNonWhitespaceIndex == -1) { + firstNonWhitespaceIndex = str.length(); + } + return TextUtils.normalizeIndentationFromWhitespace(str.substring(0, firstNonWhitespaceIndex), tabSize, + insertSpaces) + str.substring(firstNonWhitespaceIndex); + } + + private static String normalizeIndentationFromWhitespace(final String str, final int tabSize, + final boolean insertSpaces) { + int spacesCnt = 0; + for (int i = 0; i < str.length(); i++) { + if (str.charAt(i) == '\t') { + spacesCnt += tabSize; + } else { + spacesCnt++; + } + } + + final StringBuilder result = new StringBuilder(); + if (!insertSpaces) { + final long tabsCnt = Math.round(Math.floor(spacesCnt / tabSize)); + spacesCnt = spacesCnt % tabSize; + for (int i = 0; i < tabsCnt; i++) { + result.append('\t'); + } + } + + for (int i = 0; i < spacesCnt; i++) { + result.append(' '); + } + + return result.toString(); + } + + /** + * Returns the start of the string at the offset in the text. If the string is + * not in the text at the offset, returns -1.
    + * Ex:
    + * text = "apple banana", offset=8, string="banana" returns=6 + */ + public static int startIndexOfOffsetTouchingString(final String text, final int offset, final String string) { + int start = offset - string.length(); + start = start < 0 ? 0 : start; + int end = offset + string.length(); + end = end >= text.length() ? text.length() : end; + try { + final int indexInSubtext = text.substring(start, end).indexOf(string); + return indexInSubtext == -1 ? -1 : start + indexInSubtext; + } catch (final IndexOutOfBoundsException e) { + return -1; + } + } + + /** + * Returns first index of the string that is not whitespace. If string is empty + * or contains only whitespaces, returns -1 + */ + private static int firstNonWhitespaceIndex(final String str) { + for (int i = 0, len = str.length(); i < len; i++) { + final char c = str.charAt(i); + if (c != ' ' && c != '\t') { + return i; + } + } + return -1; + } + + public static String getIndentationFromWhitespace(final String whitespace, final TabSpacesInfo tabSpaces) { + final String tab = "\t"; //$NON-NLS-1$ + int indentOffset = 0; + boolean startsWithTab = true; + boolean startsWithSpaces = true; + final String spaces = tabSpaces.isInsertSpaces() + ? " ".repeat(tabSpaces.getTabSize()) + : ""; + while (startsWithTab || startsWithSpaces) { + startsWithTab = whitespace.startsWith(tab, indentOffset); + startsWithSpaces = tabSpaces.isInsertSpaces() && whitespace.startsWith(spaces, indentOffset); + if (startsWithTab) { + indentOffset += tab.length(); + } + if (startsWithSpaces) { + indentOffset += spaces.length(); + } + } + return whitespace.substring(0, indentOffset); + } + + public static String getLinePrefixingWhitespaceAtPosition(final IDocument d, final int offset) { + try { + // find start of line + final int p = offset; + final IRegion info = d.getLineInformationOfOffset(p); + final int start = info.getOffset(); + + // find white spaces + final int end = findEndOfWhiteSpace(d, start, offset); + + return d.get(start, end - start); + } catch (final BadLocationException excp) { + // stop work + } + return ""; //$NON-NLS-1$ + } + + /** + * Returns the first offset greater than offset and smaller than + * end whose character is not a space or tab character. If no such + * offset is found, end is returned. + * + * @param document the document to search in + * @param offset the offset at which searching start + * @param end the offset at which searching stops + * + * @return the offset in the specified range whose character is not a space or + * tab + * + * @exception BadLocationException if position is an invalid range in the given + * document + */ + private static int findEndOfWhiteSpace(final IDocument document, int offset, final int end) + throws BadLocationException { + while (offset < end) { + final char c = document.getChar(offset); + if (c != ' ' && c != '\t') { + return offset; + } + offset++; + } + return end; + } + + public static TabSpacesInfo getTabSpaces(@Nullable final ITextViewer viewer) { + if (viewer != null) { + final TabsToSpacesConverter converter = ClassHelper.getFieldValue(viewer, "fTabsToSpacesConverter", //$NON-NLS-1$ + TextViewer.class); + if (converter != null) { + final int tabSize = ClassHelper.getFieldValue(converter, "fTabRatio", TabsToSpacesConverter.class); //$NON-NLS-1$ + return new TabSpacesInfo(tabSize, true); + } + } + return new TabSpacesInfo(-1, false); + } + +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/utils/package-info.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/utils/package-info.java new file mode 100644 index 000000000..859e73ca3 --- /dev/null +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/utils/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.languageconfiguration.internal.utils; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/AutoClosingPairConditionalTableWidget.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/AutoClosingPairConditionalTableWidget.java index ab65db884..0744e3ee9 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/AutoClosingPairConditionalTableWidget.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/AutoClosingPairConditionalTableWidget.java @@ -11,6 +11,7 @@ */ package org.eclipse.tm4e.languageconfiguration.internal.widgets; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.ColumnWeightData; @@ -21,29 +22,33 @@ import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationMessages; import org.eclipse.tm4e.languageconfiguration.internal.supports.AutoClosingPairConditional; -public class AutoClosingPairConditionalTableWidget extends CharacterPairsTableWidget { +final class AutoClosingPairConditionalTableWidget extends CharacterPairsTableWidget { - public AutoClosingPairConditionalTableWidget(Table table) { + AutoClosingPairConditionalTableWidget(final Table table) { super(table); setLabelProvider(new AutoClosingPairConditionalLabelProvider()); - GC gc = new GC(table.getShell()); + + final GC gc = new GC(table.getShell()); gc.setFont(JFaceResources.getDialogFont()); - TableColumnLayout columnLayout = new TableColumnLayout(); + final TableColumnLayout columnLayout = new TableColumnLayout(); - TableColumn column2 = new TableColumn(table, SWT.NONE); + final TableColumn column2 = new TableColumn(table, SWT.NONE); column2.setText(LanguageConfigurationMessages.AutoClosingPairConditionalTableWidget_notIn); - int minWidth = computeMinimumColumnWidth(gc, + final int minWidth = computeMinimumColumnWidth(gc, LanguageConfigurationMessages.AutoClosingPairConditionalTableWidget_notIn); columnLayout.setColumnData(column2, new ColumnWeightData(2, minWidth, true)); + + gc.dispose(); } - protected class AutoClosingPairConditionalLabelProvider extends CharacterPairLabelProvider { + private static final class AutoClosingPairConditionalLabelProvider extends CharacterPairLabelProvider { + @Nullable @Override - public String getColumnText(Object element, int columnIndex) { + public String getColumnText(@Nullable final Object element, final int columnIndex) { if (columnIndex == 2) { if ((element instanceof AutoClosingPairConditional)) { - AutoClosingPairConditional conditionalPair = (AutoClosingPairConditional) element; + final AutoClosingPairConditional conditionalPair = (AutoClosingPairConditional) element; return String.join(", ", conditionalPair.getNotIn()); //$NON-NLS-1$ } return ""; //$NON-NLS-1$ diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/CharacterPairsTableWidget.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/CharacterPairsTableWidget.java index 6ce7ffee9..b510e9915 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/CharacterPairsTableWidget.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/CharacterPairsTableWidget.java @@ -1,19 +1,20 @@ /** - * Copyright (c) 2018 Red Hat Inc. and others. + * Copyright (c) 2018 Red Hat Inc. and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * - * Contributors: - * Lucas Bullen (Red Hat Inc.) - initial API and implementation + * Contributors: + * Lucas Bullen (Red Hat Inc.) - initial API and implementation */ package org.eclipse.tm4e.languageconfiguration.internal.widgets; import java.util.Collections; import java.util.List; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.ColumnWeightData; @@ -30,46 +31,49 @@ import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationMessages; import org.eclipse.tm4e.languageconfiguration.internal.supports.CharacterPair; -public class CharacterPairsTableWidget extends TableViewer { +class CharacterPairsTableWidget extends TableViewer { - public CharacterPairsTableWidget(Table table) { + CharacterPairsTableWidget(final Table table) { super(table); setContentProvider(new CharacterPairContentProvider()); setLabelProvider(new CharacterPairLabelProvider()); - GC gc = new GC(table.getShell()); + final GC gc = new GC(table.getShell()); gc.setFont(JFaceResources.getDialogFont()); - TableColumnLayout columnLayout = new TableColumnLayout(); + final TableColumnLayout columnLayout = new TableColumnLayout(); - TableColumn column1 = new TableColumn(table, SWT.NONE); + final TableColumn column1 = new TableColumn(table, SWT.NONE); column1.setText(LanguageConfigurationMessages.CharacterPairsTableWidget_start); int minWidth = computeMinimumColumnWidth(gc, LanguageConfigurationMessages.CharacterPairsTableWidget_start); columnLayout.setColumnData(column1, new ColumnWeightData(2, minWidth, true)); - TableColumn column2 = new TableColumn(table, SWT.NONE); + final TableColumn column2 = new TableColumn(table, SWT.NONE); column2.setText(LanguageConfigurationMessages.CharacterPairsTableWidget_end); minWidth = computeMinimumColumnWidth(gc, LanguageConfigurationMessages.CharacterPairsTableWidget_end); columnLayout.setColumnData(column2, new ColumnWeightData(2, minWidth, true)); + + gc.dispose(); } - protected int computeMinimumColumnWidth(GC gc, String string) { + protected int computeMinimumColumnWidth(final GC gc, final String string) { return gc.stringExtent(string).x + 10; } - protected class CharacterPairContentProvider implements IStructuredContentProvider { + private static final class CharacterPairContentProvider implements IStructuredContentProvider { - private List characterPairList; + private List characterPairList = Collections.emptyList(); @Override - public Object[] getElements(Object input) { - return characterPairList.toArray(new CharacterPair[characterPairList.size()]); + public Object[] getElements(@Nullable final Object input) { + return characterPairList.toArray(CharacterPair[]::new); } @SuppressWarnings("unchecked") @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + public void inputChanged(@Nullable final Viewer viewer, @Nullable final Object oldInput, + @Nullable final Object newInput) { if (newInput == null) { - characterPairList = Collections.EMPTY_LIST; + characterPairList = Collections.emptyList(); } else { characterPairList = (List) newInput; } @@ -77,25 +81,31 @@ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { @Override public void dispose() { - characterPairList = null; + characterPairList = Collections.emptyList(); } } - protected class CharacterPairLabelProvider extends LabelProvider implements ITableLabelProvider { + protected static class CharacterPairLabelProvider extends LabelProvider implements ITableLabelProvider { + @Nullable @Override - public Image getColumnImage(Object element, int columnIndex) { + public Image getColumnImage(@Nullable final Object element, final int columnIndex) { return null; } + @Nullable @Override - public String getText(Object element) { + public String getText(@Nullable final Object element) { return getColumnText(element, 0); } + @Nullable @Override - public String getColumnText(Object element, int columnIndex) { - CharacterPair pair = (CharacterPair) element; + public String getColumnText(@Nullable final Object element, final int columnIndex) { + if (element == null) + return null; + + final CharacterPair pair = (CharacterPair) element; switch (columnIndex) { case 0: diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/ColumnSelectionAdapter.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/ColumnSelectionAdapter.java index f063baf69..ac9729d35 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/ColumnSelectionAdapter.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/ColumnSelectionAdapter.java @@ -11,6 +11,7 @@ */ package org.eclipse.tm4e.languageconfiguration.internal.widgets; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; @@ -21,14 +22,14 @@ * Sort the selected column and refresh the viewer. * */ -public class ColumnSelectionAdapter extends SelectionAdapter { +public final class ColumnSelectionAdapter extends SelectionAdapter { private final TableColumn fTableColumn; private final TableViewer tableViewer; private final int fColumnIndex; private final ColumnViewerComparator viewerComparator; - public ColumnSelectionAdapter(TableColumn column, TableViewer tableViewer, int index, ColumnViewerComparator vc) { + public ColumnSelectionAdapter(final TableColumn column, final TableViewer tableViewer, final int index, final ColumnViewerComparator vc) { fTableColumn = column; this.tableViewer = tableViewer; fColumnIndex = index; @@ -36,10 +37,10 @@ public ColumnSelectionAdapter(TableColumn column, TableViewer tableViewer, int i } @Override - public void widgetSelected(SelectionEvent e) { + public void widgetSelected(@Nullable final SelectionEvent e) { viewerComparator.setColumn(fColumnIndex); - int dir = viewerComparator.getDirection(); - Table table = tableViewer.getTable(); + final int dir = viewerComparator.getDirection(); + final Table table = tableViewer.getTable(); table.setSortDirection(dir); table.setSortColumn(fTableColumn); tableViewer.refresh(); diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/ColumnViewerComparator.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/ColumnViewerComparator.java index f9833d9fd..7aa5622f6 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/ColumnViewerComparator.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/ColumnViewerComparator.java @@ -11,6 +11,7 @@ */ package org.eclipse.tm4e.languageconfiguration.internal.widgets; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.viewers.IBaseLabelProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.TableViewer; @@ -22,16 +23,10 @@ * Viewer compoarator which sort a given column. * */ -public class ColumnViewerComparator extends ViewerComparator { +public final class ColumnViewerComparator extends ViewerComparator { - private int fSortColumn; - - private int fSortOrder; // 1 = asc, -1 = desc - - public ColumnViewerComparator() { - fSortColumn = 0; - fSortOrder = 1; - } + private int fSortColumn = 0; + private int fSortOrder = 1; // 1 = asc, -1 = desc /** * Returns the {@linkplain SWT} style constant for the sort direction. @@ -48,7 +43,7 @@ public int getDirection() { * * @param column New sort column */ - public void setColumn(int column) { + public void setColumn(final int column) { if (column == fSortColumn) { fSortOrder *= -1; } else { @@ -58,14 +53,14 @@ public void setColumn(int column) { } @Override - public int compare(Viewer viewer, Object e1, Object e2) { + public int compare(@Nullable final Viewer viewer, @Nullable final Object e1, @Nullable final Object e2) { if (viewer instanceof TableViewer) { - IBaseLabelProvider baseLabel = ((TableViewer) viewer).getLabelProvider(); + final IBaseLabelProvider baseLabel = ((TableViewer) viewer).getLabelProvider(); - String left = ((ITableLabelProvider) baseLabel).getColumnText(e1, fSortColumn); - String right = ((ITableLabelProvider) baseLabel).getColumnText(e2, fSortColumn); - int sortResult = getComparator().compare(left != null ? left : "", right != null ? right : ""); //$NON-NLS-1$ //$NON-NLS-2$ + final String left = ((ITableLabelProvider) baseLabel).getColumnText(e1, fSortColumn); + final String right = ((ITableLabelProvider) baseLabel).getColumnText(e2, fSortColumn); + final int sortResult = getComparator().compare(left != null ? left : "", right != null ? right : ""); //$NON-NLS-1$ //$NON-NLS-2$ return sortResult * fSortOrder; } diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/LanguageConfigurationInfoWidget.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/LanguageConfigurationInfoWidget.java index 2f893d13a..892a642af 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/LanguageConfigurationInfoWidget.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/LanguageConfigurationInfoWidget.java @@ -1,19 +1,22 @@ /** - * Copyright (c) 2018 Red Hat Inc. and others. + * Copyright (c) 2018 Red Hat Inc. and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * - * Contributors: - * Lucas Bullen (Red Hat Inc.) - initial API and implementation + * Contributors: + * Lucas Bullen (Red Hat Inc.) - initial API and implementation */ package org.eclipse.tm4e.languageconfiguration.internal.widgets; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; @@ -30,26 +33,15 @@ import org.eclipse.tm4e.languageconfiguration.internal.supports.Comments; import org.eclipse.tm4e.languageconfiguration.internal.supports.Folding; +@NonNullByDefault({}) public class LanguageConfigurationInfoWidget extends Composite { - public LanguageConfigurationInfoWidget(Composite parent, int style) { - super(parent, style); - GridLayout layout = new GridLayout(); - layout.marginHeight = 0; - layout.marginWidth = 0; - layout.marginLeft = 0; - layout.marginRight = 0; - super.setLayout(layout); - super.setLayoutData(new GridData(GridData.FILL_BOTH)); - createUI(this); - } - - protected TabItem commentsTab; + private TabItem commentsTab; private Text lineCommentText; private Text blockCommentStartText; private Text blockCommentEndText; - protected TabItem bracketsTab; + private TabItem bracketsTab; private CharacterPairsTableWidget bracketsTable; protected TabItem autoClosingPairsTab; @@ -58,21 +50,34 @@ public LanguageConfigurationInfoWidget(Composite parent, int style) { protected TabItem surroundingPairsTab; private CharacterPairsTableWidget surroundingPairsTable; - protected TabItem foldingTab; + private TabItem foldingTab; private Text offsideText; private Text markersStartText; private Text markersEndText; - protected TabItem wordPatternTab; + private TabItem wordPatternTab; + private Text wordPatternText; protected TabItem onEnterRulesTab; private OnEnterRuleTableWidget onEnterRuleTable; - private void createUI(Composite ancestor) { - TabFolder folder = new TabFolder(ancestor, SWT.NONE); + public LanguageConfigurationInfoWidget(final Composite parent, final int style) { + super(parent, style); + final GridLayout layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + layout.marginLeft = 0; + layout.marginRight = 0; + super.setLayout(layout); + super.setLayoutData(new GridData(GridData.FILL_BOTH)); + createUI(this); + } + + private void createUI(final Composite ancestor) { + final TabFolder folder = new TabFolder(ancestor, SWT.NONE); - GridData gd = new GridData(GridData.FILL_HORIZONTAL); + final GridData gd = new GridData(GridData.FILL_HORIZONTAL); folder.setLayoutData(gd); createCommentsTab(folder); @@ -84,7 +89,7 @@ private void createUI(Composite ancestor) { createOnEnterRulesTab(folder); } - public void refresh(ILanguageConfiguration configuration) { + public void refresh(@Nullable final ILanguageConfiguration configuration) { lineCommentText.setText(""); //$NON-NLS-1$ blockCommentStartText.setText(""); //$NON-NLS-1$ blockCommentEndText.setText(""); //$NON-NLS-1$ @@ -101,13 +106,13 @@ public void refresh(ILanguageConfiguration configuration) { return; } - Comments comments = configuration.getComments(); + final Comments comments = configuration.getComments(); if (comments != null) { lineCommentText.setText(comments.getLineComment() == null ? "" : comments.getLineComment()); - CharacterPair blockComment = comments.getBlockComment(); + final CharacterPair blockComment = comments.getBlockComment(); if (blockComment != null) { - blockCommentStartText.setText(comments.getBlockComment().getKey()); - blockCommentEndText.setText(comments.getBlockComment().getValue()); + blockCommentStartText.setText(blockComment.getKey()); + blockCommentEndText.setText(blockComment.getValue()); } } @@ -115,14 +120,14 @@ public void refresh(ILanguageConfiguration configuration) { autoClosingPairsTable.setInput(removeNullElements(configuration.getAutoClosingPairs())); surroundingPairsTable.setInput(removeNullElements(configuration.getSurroundingPairs())); - Folding folding = configuration.getFolding(); + final Folding folding = configuration.getFolding(); if (folding != null) { offsideText.setText(folding.getOffSide().toString()); markersStartText.setText(folding.getMarkersStart()); markersEndText.setText(folding.getMarkersEnd()); } - String wordPattern = configuration.getWordPattern(); + final String wordPattern = configuration.getWordPattern(); if (wordPattern != null) { wordPatternText.setText(wordPattern); } @@ -130,16 +135,17 @@ public void refresh(ILanguageConfiguration configuration) { onEnterRuleTable.setInput(removeNullElements(configuration.getOnEnterRules())); } - private List removeNullElements(List list) { + @Nullable + private List removeNullElements(@Nullable final List list) { if (list == null) { return null; } - return list.stream().filter(el -> el != null).collect(Collectors.toList()); + return list.stream().filter(Objects::nonNull).collect(Collectors.toList()); } - protected void createCommentsTab(TabFolder folder) { + private void createCommentsTab(final TabFolder folder) { commentsTab = createTab(folder, LanguageConfigurationMessages.LanguageConfigurationInfoWidget_comments); - Composite parent = (Composite) commentsTab.getControl(); + final Composite parent = (Composite) commentsTab.getControl(); lineCommentText = createText(parent, LanguageConfigurationMessages.LanguageConfigurationInfoWidget_lineComments); @@ -149,28 +155,28 @@ protected void createCommentsTab(TabFolder folder) { LanguageConfigurationMessages.LanguageConfigurationInfoWidget_blockCommentsEnd); } - protected void createBracketsTab(TabFolder folder) { + private void createBracketsTab(final TabFolder folder) { bracketsTab = createTab(folder, LanguageConfigurationMessages.LanguageConfigurationInfoWidget_brackets); bracketsTable = new CharacterPairsTableWidget(createTable((Composite) bracketsTab.getControl())); } - protected void createAutoClosingPairsTab(TabFolder folder) { + protected void createAutoClosingPairsTab(final TabFolder folder) { autoClosingPairsTab = createTab(folder, LanguageConfigurationMessages.LanguageConfigurationInfoWidget_autoClosingPairs); autoClosingPairsTable = new AutoClosingPairConditionalTableWidget( createTable((Composite) autoClosingPairsTab.getControl())); } - protected void createSurroundingPairsTab(TabFolder folder) { + protected void createSurroundingPairsTab(final TabFolder folder) { surroundingPairsTab = createTab(folder, LanguageConfigurationMessages.LanguageConfigurationInfoWidget_surroundingPairs); surroundingPairsTable = new CharacterPairsTableWidget( createTable((Composite) surroundingPairsTab.getControl())); } - protected void createFoldingTab(TabFolder folder) { + private void createFoldingTab(final TabFolder folder) { foldingTab = createTab(folder, LanguageConfigurationMessages.LanguageConfigurationInfoWidget_folding_title); - Composite parent = (Composite) foldingTab.getControl(); + final Composite parent = (Composite) foldingTab.getControl(); offsideText = createText(parent, LanguageConfigurationMessages.LanguageConfigurationInfoWidget_offSide); offsideText.setToolTipText(LanguageConfigurationMessages.LanguageConfigurationInfoWidget_offSide_tooltip); @@ -179,36 +185,36 @@ protected void createFoldingTab(TabFolder folder) { markersEndText = createText(parent, LanguageConfigurationMessages.LanguageConfigurationInfoWidget_end); } - protected void createWordPatternTab(TabFolder folder) { + private void createWordPatternTab(final TabFolder folder) { wordPatternTab = createTab(folder, LanguageConfigurationMessages.LanguageConfigurationInfoWidget_wordPattern_title); - Composite parent = (Composite) wordPatternTab.getControl(); + final Composite parent = (Composite) wordPatternTab.getControl(); wordPatternText = createText(parent, LanguageConfigurationMessages.LanguageConfigurationInfoWidget_wordPattern_message); } - protected void createOnEnterRulesTab(TabFolder folder) { + protected void createOnEnterRulesTab(final TabFolder folder) { onEnterRulesTab = createTab(folder, LanguageConfigurationMessages.LanguageConfigurationInfoWidget_onEnterRules); onEnterRuleTable = new OnEnterRuleTableWidget(createTable((Composite) onEnterRulesTab.getControl())); } - private Table createTable(Composite parent) { - Composite tableComposite = new Composite(parent, SWT.NONE); + private Table createTable(final Composite parent) { + final Composite tableComposite = new Composite(parent, SWT.NONE); tableComposite.setLayoutData(new GridData(GridData.FILL_BOTH)); tableComposite.setLayout(new TableColumnLayout()); - Table table = new Table(tableComposite, + final Table table = new Table(tableComposite, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL); table.setHeaderVisible(true); table.setLinesVisible(true); return table; } - private TabItem createTab(TabFolder folder, String title) { - TabItem tab = new TabItem(folder, SWT.NONE); + private TabItem createTab(final TabFolder folder, final String title) { + final TabItem tab = new TabItem(folder, SWT.NONE); tab.setText(title); - Composite parent = new Composite(folder, SWT.NONE); + final Composite parent = new Composite(folder, SWT.NONE); parent.setLayout(new GridLayout()); parent.setLayoutData(new GridData(GridData.FILL_BOTH)); tab.setControl(parent); @@ -216,11 +222,11 @@ private TabItem createTab(TabFolder folder, String title) { return tab; } - protected Text createText(Composite parent, String s) { - Label label = new Label(parent, SWT.NONE); + private Text createText(final Composite parent, final String s) { + final Label label = new Label(parent, SWT.NONE); label.setText(s); - Text text = new Text(parent, SWT.BORDER); + final Text text = new Text(parent, SWT.BORDER); text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); text.setEditable(false); return text; diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/LanguageConfigurationPreferencesWidget.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/LanguageConfigurationPreferencesWidget.java index 5ed2cbff9..af00617d8 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/LanguageConfigurationPreferencesWidget.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/LanguageConfigurationPreferencesWidget.java @@ -13,6 +13,8 @@ import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; @@ -21,7 +23,8 @@ import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationDefinition; import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationRegistryManager; -public class LanguageConfigurationPreferencesWidget extends LanguageConfigurationInfoWidget { +@NonNullByDefault({}) +public final class LanguageConfigurationPreferencesWidget extends LanguageConfigurationInfoWidget { private Button toggleOnEnterButton; private Button toggleBracketAutoClosingButton; @@ -30,11 +33,11 @@ public class LanguageConfigurationPreferencesWidget extends LanguageConfiguratio private ILanguageConfigurationDefinition definition; private ILanguageConfigurationRegistryManager manager; - public LanguageConfigurationPreferencesWidget(Composite parent, int style) { + public LanguageConfigurationPreferencesWidget(final Composite parent, final int style) { super(parent, style); } - public void refresh(ILanguageConfigurationDefinition definition, ILanguageConfigurationRegistryManager manager) { + public void refresh(@Nullable final ILanguageConfigurationDefinition definition, final ILanguageConfigurationRegistryManager manager) { super.refresh(definition == null ? null : definition.getLanguageConfiguration()); if (definition == null) { toggleOnEnterButton.setEnabled(false); @@ -56,9 +59,9 @@ public void refresh(ILanguageConfigurationDefinition definition, ILanguageConfig } @Override - protected void createOnEnterRulesTab(TabFolder folder) { + protected void createOnEnterRulesTab(final TabFolder folder) { super.createOnEnterRulesTab(folder); - Composite parent = (Composite) onEnterRulesTab.getControl(); + final Composite parent = (Composite) onEnterRulesTab.getControl(); toggleOnEnterButton = new Button(parent, SWT.CHECK); toggleOnEnterButton.setText("Enable on enter actions"); toggleOnEnterButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); @@ -70,18 +73,18 @@ protected void createOnEnterRulesTab(TabFolder folder) { })); } - public boolean getToggleOnEnter() { + private boolean getToggleOnEnter() { return toggleOnEnterButton.getSelection(); } - public void setToggleOnEnter(Boolean selection) { + private void setToggleOnEnter(final Boolean selection) { toggleOnEnterButton.setSelection(selection); } @Override - protected void createAutoClosingPairsTab(TabFolder folder) { + protected void createAutoClosingPairsTab(final TabFolder folder) { super.createAutoClosingPairsTab(folder); - Composite parent = (Composite) autoClosingPairsTab.getControl(); + final Composite parent = (Composite) autoClosingPairsTab.getControl(); toggleBracketAutoClosingButton = new Button(parent, SWT.CHECK); toggleBracketAutoClosingButton.setText("Enable auto closing brackets"); toggleBracketAutoClosingButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); @@ -93,18 +96,18 @@ protected void createAutoClosingPairsTab(TabFolder folder) { })); } - public boolean getBracketAutoClosing() { + private boolean getBracketAutoClosing() { return toggleBracketAutoClosingButton.getSelection(); } - public void setBracketAutoClosing(Boolean selection) { + private void setBracketAutoClosing(final Boolean selection) { toggleBracketAutoClosingButton.setSelection(selection); } @Override - protected void createSurroundingPairsTab(TabFolder folder) { + protected void createSurroundingPairsTab(final TabFolder folder) { super.createSurroundingPairsTab(folder); - Composite parent = (Composite) surroundingPairsTab.getControl(); + final Composite parent = (Composite) surroundingPairsTab.getControl(); toggleMatchingPairsButton = new Button(parent, SWT.CHECK); toggleMatchingPairsButton.setText("Enable matching brackets"); toggleMatchingPairsButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); @@ -116,11 +119,11 @@ protected void createSurroundingPairsTab(TabFolder folder) { })); } - public boolean getMatchingPairs() { + private boolean getMatchingPairs() { return toggleMatchingPairsButton.getSelection(); } - public void setMatchingPairs(Boolean selection) { + private void setMatchingPairs(final Boolean selection) { toggleMatchingPairsButton.setSelection(selection); } diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/OnEnterRuleTableWidget.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/OnEnterRuleTableWidget.java index c0e918f5a..5516c514b 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/OnEnterRuleTableWidget.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/OnEnterRuleTableWidget.java @@ -1,19 +1,20 @@ /** - * Copyright (c) 2018 Red Hat Inc. and others. + * Copyright (c) 2018 Red Hat Inc. and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * - * Contributors: - * Lucas Bullen (Red Hat Inc.) - initial API and implementation + * Contributors: + * Lucas Bullen (Red Hat Inc.) - initial API and implementation */ package org.eclipse.tm4e.languageconfiguration.internal.widgets; import java.util.Collections; import java.util.List; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.ColumnWeightData; @@ -31,61 +32,65 @@ import org.eclipse.tm4e.languageconfiguration.internal.supports.EnterAction; import org.eclipse.tm4e.languageconfiguration.internal.supports.OnEnterRule; -public class OnEnterRuleTableWidget extends TableViewer { +final class OnEnterRuleTableWidget extends TableViewer { - public OnEnterRuleTableWidget(Table table) { + OnEnterRuleTableWidget(final Table table) { super(table); setContentProvider(new OnEnterRuleContentProvider()); setLabelProvider(new OnEnterRuleLabelProvider()); - GC gc = new GC(table.getShell()); + final GC gc = new GC(table.getShell()); gc.setFont(JFaceResources.getDialogFont()); - TableColumnLayout columnLayout = new TableColumnLayout(); + final TableColumnLayout columnLayout = new TableColumnLayout(); - TableColumn column1 = new TableColumn(table, SWT.NONE); + final TableColumn column1 = new TableColumn(table, SWT.NONE); column1.setText(LanguageConfigurationMessages.OnEnterRuleTableWidget_beforeText); int minWidth = computeMinimumColumnWidth(gc, LanguageConfigurationMessages.OnEnterRuleTableWidget_beforeText); columnLayout.setColumnData(column1, new ColumnWeightData(2, minWidth, true)); - TableColumn column2 = new TableColumn(table, SWT.NONE); + final TableColumn column2 = new TableColumn(table, SWT.NONE); column2.setText(LanguageConfigurationMessages.OnEnterRuleTableWidget_afterText); minWidth = computeMinimumColumnWidth(gc, LanguageConfigurationMessages.OnEnterRuleTableWidget_afterText); columnLayout.setColumnData(column2, new ColumnWeightData(2, minWidth, true)); - TableColumn column3 = new TableColumn(table, SWT.NONE); + final TableColumn column3 = new TableColumn(table, SWT.NONE); column3.setText(LanguageConfigurationMessages.OnEnterRuleTableWidget_indentAction); minWidth = computeMinimumColumnWidth(gc, LanguageConfigurationMessages.OnEnterRuleTableWidget_indentAction); columnLayout.setColumnData(column3, new ColumnWeightData(1, minWidth, true)); - TableColumn column4 = new TableColumn(table, SWT.NONE); + final TableColumn column4 = new TableColumn(table, SWT.NONE); column4.setText(LanguageConfigurationMessages.OnEnterRuleTableWidget_appendText); minWidth = computeMinimumColumnWidth(gc, LanguageConfigurationMessages.OnEnterRuleTableWidget_appendText); columnLayout.setColumnData(column4, new ColumnWeightData(1, minWidth, true)); - TableColumn column5 = new TableColumn(table, SWT.NONE); + final TableColumn column5 = new TableColumn(table, SWT.NONE); column5.setText(LanguageConfigurationMessages.OnEnterRuleTableWidget_removeText); minWidth = computeMinimumColumnWidth(gc, LanguageConfigurationMessages.OnEnterRuleTableWidget_removeText); columnLayout.setColumnData(column5, new ColumnWeightData(1, minWidth, true)); + + gc.dispose(); } - protected int computeMinimumColumnWidth(GC gc, String string) { + private int computeMinimumColumnWidth(final GC gc, final String string) { return gc.stringExtent(string).x + 10; } - protected class OnEnterRuleContentProvider implements IStructuredContentProvider { + private static final class OnEnterRuleContentProvider implements IStructuredContentProvider { - private List onEnterRulesList; + private List onEnterRulesList = Collections.emptyList(); @Override - public Object[] getElements(Object input) { - return onEnterRulesList.toArray(new OnEnterRule[onEnterRulesList.size()]); + public Object[] getElements(@Nullable final Object input) { + assert onEnterRulesList != null; + return onEnterRulesList.toArray(OnEnterRule[]::new); } @SuppressWarnings("unchecked") @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + public void inputChanged(@Nullable final Viewer viewer, @Nullable final Object oldInput, + @Nullable final Object newInput) { if (newInput == null) { - onEnterRulesList = Collections.EMPTY_LIST; + onEnterRulesList = Collections.emptyList(); } else { onEnterRulesList = (List) newInput; } @@ -93,38 +98,48 @@ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { @Override public void dispose() { - onEnterRulesList = null; + onEnterRulesList = Collections.emptyList(); } } - protected class OnEnterRuleLabelProvider extends LabelProvider implements ITableLabelProvider { + private static final class OnEnterRuleLabelProvider extends LabelProvider implements ITableLabelProvider { + @Nullable @Override - public Image getColumnImage(Object element, int columnIndex) { + public Image getColumnImage(@Nullable final Object element, final int columnIndex) { return null; } + @Nullable @Override - public String getText(Object element) { + public String getText(@Nullable final Object element) { return getColumnText(element, 0); } + @Nullable @Override - public String getColumnText(Object element, int columnIndex) { - OnEnterRule rule = (OnEnterRule) element; - EnterAction action = rule.getAction(); + public String getColumnText(@Nullable final Object element, final int columnIndex) { + if (element == null) + return ""; + + final OnEnterRule rule = (OnEnterRule) element; + final EnterAction action = rule.getAction(); switch (columnIndex) { case 0: - return rule.getBeforeText().pattern(); + final var beforeText = rule.getBeforeText(); + return beforeText == null ? "" : beforeText.pattern(); case 1: - return rule.getAfterText() == null ? "" : rule.getAfterText().pattern(); //$NON-NLS-1$ + final var afterText = rule.getAfterText(); + return afterText == null ? "" : afterText.pattern(); //$NON-NLS-1$ case 2: return action.getIndentAction().toString(); case 3: - return action.getAppendText() == null ? "" : action.getAppendText(); //$NON-NLS-1$ + final var appendText = action.getAppendText(); + return appendText == null ? "" : appendText; //$NON-NLS-1$ case 4: - return action.getRemoveText() == null ? "" : action.getRemoveText().toString(); //$NON-NLS-1$ + final var removeText = action.getRemoveText(); + return removeText == null ? "" : removeText.toString(); //$NON-NLS-1$ default: return ""; //$NON-NLS-1$ } diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/package-info.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/package-info.java new file mode 100644 index 000000000..8242416ce --- /dev/null +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/widgets/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.languageconfiguration.internal.widgets; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/wizards/LanguageConfigurationImportWizard.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/wizards/LanguageConfigurationImportWizard.java index 914f5b1a0..5e0986f2c 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/wizards/LanguageConfigurationImportWizard.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/wizards/LanguageConfigurationImportWizard.java @@ -1,16 +1,17 @@ /** - * Copyright (c) 2018 Red Hat Inc. and others. + * Copyright (c) 2018 Red Hat Inc. and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * - * Contributors: - * Lucas Bullen (Red Hat Inc.) - initial API and implementation + * Contributors: + * Lucas Bullen (Red Hat Inc.) - initial API and implementation */ package org.eclipse.tm4e.languageconfiguration.internal.wizards; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.wizard.Wizard; import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationDefinition; @@ -24,31 +25,27 @@ * Wizard to import language configurations * */ -public class LanguageConfigurationImportWizard extends Wizard implements IImportWizard { +public final class LanguageConfigurationImportWizard extends Wizard implements IImportWizard { + @Nullable private SelectLanguageConfigurationWizardPage mainPage; + @Nullable private ILanguageConfigurationDefinition createdDefinition; private ILanguageConfigurationRegistryManager registryManager; private final boolean save; - public LanguageConfigurationImportWizard() { - this(true); - } - - public LanguageConfigurationImportWizard(boolean save) { + public LanguageConfigurationImportWizard(final boolean save) { this.save = save; - setRegistryManager(LanguageConfigurationRegistryManager.getInstance()); + this.registryManager = LanguageConfigurationRegistryManager.getInstance(); } /** * Set registry to use to add the created grammar definitions. - * - * @param grammarRegistryManager */ - public void setRegistryManager(ILanguageConfigurationRegistryManager registryManager) { + public void setRegistryManager(final ILanguageConfigurationRegistryManager registryManager) { this.registryManager = registryManager; } @@ -60,12 +57,13 @@ public void addPages() { @Override public boolean performFinish() { - ILanguageConfigurationDefinition definition = mainPage.getDefinition(); + assert mainPage != null; + final ILanguageConfigurationDefinition definition = mainPage.getDefinition(); registryManager.registerLanguageConfigurationDefinition(definition); if (save) { try { registryManager.save(); - } catch (BackingStoreException e) { + } catch (final BackingStoreException e) { e.printStackTrace(); return false; } @@ -75,10 +73,11 @@ public boolean performFinish() { } @Override - public void init(IWorkbench workbench, IStructuredSelection selection) { + public void init(@Nullable final IWorkbench workbench, @Nullable final IStructuredSelection selection) { } + @Nullable public ILanguageConfigurationDefinition getCreatedDefinition() { return createdDefinition; } diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/wizards/SelectLanguageConfigurationWizardPage.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/wizards/SelectLanguageConfigurationWizardPage.java index b4a31c65f..18486e1b9 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/wizards/SelectLanguageConfigurationWizardPage.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/wizards/SelectLanguageConfigurationWizardPage.java @@ -1,19 +1,20 @@ /** - * Copyright (c) 2018 Red Hat Inc. and others. + * Copyright (c) 2018 Red Hat Inc. and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * - * Contributors: - * Lucas Bullen (Red Hat Inc.) - initial API and implementation + * Contributors: + * Lucas Bullen (Red Hat Inc.) - initial API and implementation */ package org.eclipse.tm4e.languageconfiguration.internal.wizards; +import static org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationMessages.*; + import java.io.FileReader; import java.util.ArrayList; -import java.util.List; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; @@ -24,6 +25,7 @@ import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.content.IContentType; import org.eclipse.core.runtime.content.IContentTypeManager; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.dialogs.DialogPage; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.viewers.ITreeContentProvider; @@ -44,45 +46,43 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; -import org.eclipse.tm4e.languageconfiguration.ILanguageConfiguration; import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationDefinition; import org.eclipse.tm4e.languageconfiguration.ILanguageConfigurationRegistryManager; import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfiguration; import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationDefinition; -import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationMessages; import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfigurationPlugin; import org.eclipse.tm4e.languageconfiguration.internal.widgets.LanguageConfigurationInfoWidget; -import org.eclipse.tm4e.ui.utils.ContentTypeHelper; +import org.eclipse.tm4e.ui.internal.utils.ContentTypeHelper; import org.eclipse.ui.dialogs.ResourceSelectionDialog; -public class SelectLanguageConfigurationWizardPage extends WizardPage implements Listener { +final class SelectLanguageConfigurationWizardPage extends WizardPage implements Listener { private static final String PAGE_NAME = SelectLanguageConfigurationWizardPage.class.getName(); - protected static final String[] TEXTMATE_EXTENSIONS = new String[] { "*language-configuration.json" }; //$NON-NLS-1$ + private static final String[] TEXTMATE_EXTENSIONS = { "*language-configuration.json" }; //$NON-NLS-1$ - private Button browseFileSystemButton; - private Button browseWorkspaceButton; + @Nullable private Text fileText; + + @Nullable private Text contentTypeText; + + @Nullable private LanguageConfigurationInfoWidget infoWidget; - private ILanguageConfigurationRegistryManager registryManager; + private final ILanguageConfigurationRegistryManager registryManager; - protected SelectLanguageConfigurationWizardPage(String pageName) { - super(pageName); - } - - public SelectLanguageConfigurationWizardPage(ILanguageConfigurationRegistryManager registryManager) { + SelectLanguageConfigurationWizardPage(final ILanguageConfigurationRegistryManager registryManager) { super(PAGE_NAME); this.registryManager = registryManager; - super.setTitle(LanguageConfigurationMessages.SelectLanguageConfigurationWizardPage_page_title); - super.setDescription(LanguageConfigurationMessages.SelectLanguageConfigurationWizardPage_page_description); + super.setTitle(SelectLanguageConfigurationWizardPage_page_title); + super.setDescription(SelectLanguageConfigurationWizardPage_page_description); } @Override - public final void createControl(Composite parent) { + public final void createControl(@Nullable final Composite parent) { + assert parent != null; initializeDialogUnits(parent); - Composite topLevel = new Composite(parent, SWT.NONE); + final var topLevel = new Composite(parent, SWT.NONE); topLevel.setLayout(new GridLayout()); topLevel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL)); topLevel.setFont(parent.getFont()); @@ -93,22 +93,22 @@ public final void createControl(Composite parent) { } @Override - public void handleEvent(Event event) { + public void handleEvent(@Nullable final Event event) { validateAndUpdateStatus(event); } - private void validateAndUpdateStatus(Event event) { - IStatus status = validatePage(event); + private void validateAndUpdateStatus(@Nullable final Event event) { + final IStatus status = validatePage(event); statusChanged(status == null ? Status.OK_STATUS : status); } - public void statusChanged(IStatus status) { + private void statusChanged(final IStatus status) { setPageComplete(!status.matches(IStatus.ERROR)); applyToStatusLine(this, status); } - private static void applyToStatusLine(DialogPage page, IStatus status) { - String message = Status.OK_STATUS.equals(status) ? null : status.getMessage(); + private static void applyToStatusLine(final DialogPage page, final IStatus status) { + final var message = Status.OK_STATUS.equals(status) ? null : status.getMessage(); switch (status.getSeverity()) { case IStatus.OK: page.setMessage(message, IMessageProvider.NONE); @@ -123,194 +123,211 @@ private static void applyToStatusLine(DialogPage page, IStatus status) { page.setErrorMessage(null); break; default: - if (message != null && message.length() == 0) { - message = null; - } page.setMessage(null); - page.setErrorMessage(message); + page.setErrorMessage(message != null && message.isEmpty() ? null : message); break; } } - protected void createBody(Composite ancestor) { - Composite parent = new Composite(ancestor, SWT.NONE); + private void createBody(final Composite ancestor) { + final var parent = new Composite(ancestor, SWT.NONE); parent.setFont(parent.getFont()); parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); parent.setLayout(new GridLayout(2, false)); - fileText = createText(parent, LanguageConfigurationMessages.SelectLanguageConfigurationWizardPage_file); + final var fileText = createText(parent, SelectLanguageConfigurationWizardPage_file); + this.fileText = fileText; fileText.addListener(SWT.Modify, this); - Composite buttons = new Composite(parent, SWT.NONE); + final var buttons = new Composite(parent, SWT.NONE); buttons.setLayout(new GridLayout(2, false)); - GridData gd = new GridData(GridData.FILL_HORIZONTAL); + final var gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = 2; gd.horizontalAlignment = SWT.RIGHT; buttons.setLayoutData(gd); - infoWidget = new LanguageConfigurationInfoWidget(parent, SWT.NONE); - GridData data = new GridData(GridData.FILL_HORIZONTAL); + final var infoWidget = new LanguageConfigurationInfoWidget(parent, SWT.NONE); + this.infoWidget = infoWidget; + final var data = new GridData(GridData.FILL_HORIZONTAL); data.horizontalSpan = 2; infoWidget.setLayoutData(data); - browseFileSystemButton = new Button(buttons, SWT.NONE); - browseFileSystemButton - .setText(LanguageConfigurationMessages.SelectLanguageConfigurationWizardPage_browse_fileSystem); + final var browseFileSystemButton = new Button(buttons, SWT.NONE); + browseFileSystemButton.setText(SelectLanguageConfigurationWizardPage_browse_fileSystem); browseFileSystemButton.addSelectionListener(new SelectionAdapter() { @Override - public void widgetSelected(SelectionEvent e) { - FileDialog dialog = new FileDialog(parent.getShell()); + public void widgetSelected(@Nullable final SelectionEvent e) { + final var dialog = new FileDialog(parent.getShell()); dialog.setFilterExtensions(TEXTMATE_EXTENSIONS); dialog.setFilterPath(fileText.getText()); - String result = dialog.open(); - if (result != null && result.length() > 0) { + final String result = dialog.open(); + if (result != null && !result.isEmpty()) { fileText.setText(result); } } }); - browseWorkspaceButton = new Button(buttons, SWT.NONE); - browseWorkspaceButton - .setText(LanguageConfigurationMessages.SelectLanguageConfigurationWizardPage_browse_workspace); + final var browseWorkspaceButton = new Button(buttons, SWT.NONE); + browseWorkspaceButton.setText(SelectLanguageConfigurationWizardPage_browse_workspace); browseWorkspaceButton.addSelectionListener(new SelectionAdapter() { @Override - public void widgetSelected(SelectionEvent e) { - ResourceSelectionDialog dialog = new ResourceSelectionDialog(browseWorkspaceButton.getShell(), + public void widgetSelected(@Nullable final SelectionEvent e) { + final var dialog = new ResourceSelectionDialog(browseWorkspaceButton.getShell(), ResourcesPlugin.getWorkspace().getRoot(), - LanguageConfigurationMessages.SelectLanguageConfigurationWizardPage_workspace_description); - dialog.setTitle(LanguageConfigurationMessages.SelectLanguageConfigurationWizardPage_workspace_title); - int returnCode = dialog.open(); - Object[] results = dialog.getResult(); + SelectLanguageConfigurationWizardPage_workspace_description); + dialog.setTitle(SelectLanguageConfigurationWizardPage_workspace_title); + final int returnCode = dialog.open(); + final Object[] results = dialog.getResult(); if (returnCode == 0 && results.length > 0) { fileText.setText(((IResource) results[0]).getFullPath().makeRelative().toString()); } } }); contentTypeText = createText(parent, - LanguageConfigurationMessages.SelectLanguageConfigurationWizardPage_contentType); + SelectLanguageConfigurationWizardPage_contentType); contentTypeText.addListener(SWT.Modify, this); createContentTypeTreeViewer(parent); } - private void createContentTypeTreeViewer(Composite composite) { - TreeViewer contentTypesViewer = new TreeViewer(composite, + private void createContentTypeTreeViewer(final Composite composite) { + final var contentTypesViewer = new TreeViewer(composite, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); contentTypesViewer.getControl().setFont(composite.getFont()); contentTypesViewer.setContentProvider(new ContentTypesContentProvider()); contentTypesViewer.setLabelProvider(new ContentTypesLabelProvider()); contentTypesViewer.setComparator(new ViewerComparator()); contentTypesViewer.setInput(Platform.getContentTypeManager()); - GridData data = new GridData(GridData.FILL_HORIZONTAL); + final var data = new GridData(GridData.FILL_HORIZONTAL); data.horizontalSpan = 2; contentTypesViewer.getControl().setLayoutData(data); - contentTypesViewer.addSelectionChangedListener(event -> contentTypeText - .setText(((IContentType) event.getStructuredSelection().getFirstElement()).toString())); + contentTypesViewer.addSelectionChangedListener(event -> { + final var contentTypeText = this.contentTypeText; + if (contentTypeText != null) { + contentTypeText.setText(((IContentType) event.getStructuredSelection().getFirstElement()).toString()); + } + }); } - private class ContentTypesLabelProvider extends LabelProvider { + private static final class ContentTypesLabelProvider extends LabelProvider { @Override - public String getText(Object element) { - IContentType contentType = (IContentType) element; + public String getText(@Nullable final Object element) { + if (element == null) + return ""; + final IContentType contentType = (IContentType) element; return contentType.getName(); } } - private class ContentTypesContentProvider implements ITreeContentProvider { + private static final class ContentTypesContentProvider implements ITreeContentProvider { private IContentTypeManager manager = Platform.getContentTypeManager(); @Override - public Object[] getChildren(Object parentElement) { - List elements = new ArrayList<>(); - IContentType baseType = (IContentType) parentElement; - for (IContentType contentType : manager.getAllContentTypes()) { + public Object[] getChildren(@Nullable final Object parentElement) { + final var elements = new ArrayList<>(); + final var baseType = (IContentType) parentElement; + for (final var contentType : manager.getAllContentTypes()) { if ((contentType.getBaseType() == null && baseType == null) - || ((contentType.getBaseType() != null && contentType.getBaseType().equals(baseType)))) { + || (contentType.getBaseType() != null && contentType.getBaseType().equals(baseType))) { elements.add(contentType); } } return elements.toArray(); } + @Nullable @Override - public Object getParent(Object element) { - IContentType contentType = (IContentType) element; + public Object getParent(@Nullable final Object element) { + if (element == null) + return null; + final IContentType contentType = (IContentType) element; return contentType.getBaseType(); } @Override - public boolean hasChildren(Object element) { + public boolean hasChildren(@Nullable final Object element) { return getChildren(element).length > 0; } @Override - public Object[] getElements(Object inputElement) { + public Object[] getElements(@Nullable final Object inputElement) { return getChildren(null); } @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - manager = (IContentTypeManager) newInput; + public void inputChanged(@Nullable final Viewer viewer, @Nullable final Object oldInput, + @Nullable final Object newInput) { + manager = newInput == null ? Platform.getContentTypeManager() : (IContentTypeManager) newInput; } } - private Text createText(Composite parent, String s) { - Label label = new Label(parent, SWT.NONE); + private Text createText(final Composite parent, final String s) { + final var label = new Label(parent, SWT.NONE); label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); label.setText(s); - Text text = new Text(parent, SWT.BORDER); + final var text = new Text(parent, SWT.BORDER); text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); return text; } - protected IStatus validatePage(Event event) { + @Nullable + private IStatus validatePage(@Nullable final Event event) { + final var infoWidget = this.infoWidget; + assert infoWidget != null; infoWidget.refresh(null); - String path = fileText.getText(); + + final var fileText = this.fileText; + assert fileText != null; + final String path = fileText.getText(); if (path.length() == 0) { return new Status(IStatus.ERROR, LanguageConfigurationPlugin.PLUGIN_ID, - LanguageConfigurationMessages.SelectLanguageConfigurationWizardPage_fileError_noSelection); + SelectLanguageConfigurationWizardPage_fileError_noSelection); } IPath p = new Path(path); if (!p.isAbsolute()) { p = ResourcesPlugin.getWorkspace().getRoot().getFile(p).getLocation(); } - try { - ILanguageConfiguration configuration = LanguageConfiguration.load(new FileReader(p.toFile())); + try (var file = new FileReader(p.toFile())) { + final var configuration = LanguageConfiguration.load(file); if (configuration == null) { return new Status(IStatus.ERROR, LanguageConfigurationPlugin.PLUGIN_ID, - LanguageConfigurationMessages.SelectLanguageConfigurationWizardPage_fileError_invalid); + SelectLanguageConfigurationWizardPage_fileError_invalid); } infoWidget.refresh(configuration); - } catch (Exception e) { + } catch (final Exception e) { return new Status(IStatus.ERROR, LanguageConfigurationPlugin.PLUGIN_ID, - LanguageConfigurationMessages.SelectLanguageConfigurationWizardPage_fileError_error - + e.getLocalizedMessage()); + SelectLanguageConfigurationWizardPage_fileError_error + e.getLocalizedMessage()); } - if (contentTypeText.getText().isEmpty()) { + + final var contentTypeText = this.contentTypeText; + if (contentTypeText == null || contentTypeText.getText().isEmpty()) { return new Status(IStatus.ERROR, LanguageConfigurationPlugin.PLUGIN_ID, - LanguageConfigurationMessages.SelectLanguageConfigurationWizardPage_contentTypeError_noSelection); + SelectLanguageConfigurationWizardPage_contentTypeError_noSelection); } - IContentType contentType = ContentTypeHelper.getContentTypeById(contentTypeText.getText()); + final var contentType = ContentTypeHelper.getContentTypeById(contentTypeText.getText()); if (contentType == null) { return new Status(IStatus.ERROR, LanguageConfigurationPlugin.PLUGIN_ID, - LanguageConfigurationMessages.SelectLanguageConfigurationWizardPage_contentTypeError_invalid); + SelectLanguageConfigurationWizardPage_contentTypeError_invalid); } - if (registryManager.getLanguageConfigurationFor(new IContentType[] { contentType }) != null) { + if (registryManager.getLanguageConfigurationFor(contentType) != null) { return new Status(IStatus.WARNING, LanguageConfigurationPlugin.PLUGIN_ID, - LanguageConfigurationMessages.SelectLanguageConfigurationWizardPage_contentTypeWarning_duplicate); + SelectLanguageConfigurationWizardPage_contentTypeWarning_duplicate); } return null; } - public ILanguageConfigurationDefinition getDefinition() { - IPath p = new Path(fileText.getText()); - if (!p.isAbsolute()) { - p = ResourcesPlugin.getWorkspace().getRoot().getFile(p).getLocation(); + ILanguageConfigurationDefinition getDefinition() { + assert fileText != null; + IPath path = new Path(fileText.getText()); + if (!path.isAbsolute()) { + path = ResourcesPlugin.getWorkspace().getRoot().getFile(path).getLocation(); } - return new LanguageConfigurationDefinition(ContentTypeHelper.getContentTypeById(contentTypeText.getText()), - p.toString()); - } + assert contentTypeText != null; + final var contentType = ContentTypeHelper.getContentTypeById(contentTypeText.getText()); + assert contentType != null; + return new LanguageConfigurationDefinition(contentType, path.toString()); + } } diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/wizards/package-info.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/wizards/package-info.java new file mode 100644 index 000000000..f75b58cd3 --- /dev/null +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/wizards/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.languageconfiguration.internal.wizards; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/package-info.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/package-info.java new file mode 100644 index 000000000..6ff0e49e9 --- /dev/null +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.languageconfiguration; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui.tests/src/main/resources/.gitkeep b/org.eclipse.tm4e.languageconfiguration/src/main/resources/.gitkeep similarity index 100% rename from org.eclipse.tm4e.ui.tests/src/main/resources/.gitkeep rename to org.eclipse.tm4e.languageconfiguration/src/main/resources/.gitkeep diff --git a/org.eclipse.tm4e.languageconfiguration/src/test/java/org/eclipse/tm4e/languageconfiguration/internal/supports/OnEnterSupportTest.java b/org.eclipse.tm4e.languageconfiguration/src/test/java/org/eclipse/tm4e/languageconfiguration/internal/supports/OnEnterSupportTest.java index 98e28a695..bcff89389 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/test/java/org/eclipse/tm4e/languageconfiguration/internal/supports/OnEnterSupportTest.java +++ b/org.eclipse.tm4e.languageconfiguration/src/test/java/org/eclipse/tm4e/languageconfiguration/internal/supports/OnEnterSupportTest.java @@ -1,151 +1,152 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.languageconfiguration.internal.supports; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; - -import java.util.Arrays; - -import org.eclipse.tm4e.languageconfiguration.internal.supports.EnterAction.IndentAction; -import org.junit.jupiter.api.Test; - -/** - * {@link OnEnterSupport} tests. - * - */ -public class OnEnterSupportTest { - - @Test - public void useBrackets() { - UseBracketsTest support = new UseBracketsTest(); - - support.testIndentAction("a", "", IndentAction.None); - support.testIndentAction("", "b", IndentAction.None); - support.testIndentAction("(", "b", IndentAction.Indent); - support.testIndentAction("a", ")", IndentAction.None); - support.testIndentAction("begin", "ending", IndentAction.Indent); - support.testIndentAction("abegin", "end", IndentAction.None); - support.testIndentAction("begin", ")", IndentAction.Indent); - support.testIndentAction("begin", "end", IndentAction.IndentOutdent); - support.testIndentAction("begin ", " end", IndentAction.IndentOutdent); - support.testIndentAction(" begin", "end//as", IndentAction.IndentOutdent); - support.testIndentAction("(", ")", IndentAction.IndentOutdent); - support.testIndentAction("( ", ")", IndentAction.IndentOutdent); - support.testIndentAction("a(", ")b", IndentAction.IndentOutdent); - - support.testIndentAction("(", "", IndentAction.Indent); - support.testIndentAction("(", "foo", IndentAction.Indent); - support.testIndentAction("begin", "foo", IndentAction.Indent); - support.testIndentAction("begin", "", IndentAction.Indent); - } - - private class UseBracketsTest extends OnEnterSupport { - - public UseBracketsTest() { - super(Arrays.asList(new CharacterPair("(", ")"), new CharacterPair("begin", "end")), null); - } - - public void testIndentAction(String beforeText, String afterText, IndentAction expected) { - EnterAction actual = super.onEnter("", beforeText, afterText); - if (expected == IndentAction.None) { - assertNull(actual); - } else { - assertEquals(expected, actual.getIndentAction()); - } - } - } - - @Test - public void regExpRules() { - RegExpRulesTest support = new RegExpRulesTest(); - - support.testIndentAction("\t/**", " */", IndentAction.IndentOutdent, " * "); - support.testIndentAction("\t/**", "", IndentAction.None, " * "); - support.testIndentAction("\t/** * / * / * /", "", IndentAction.None, " * "); - support.testIndentAction("\t/** /*", "", IndentAction.None, " * "); - support.testIndentAction("/**", "", IndentAction.None, " * "); - support.testIndentAction("\t/**/", "", null, null); - support.testIndentAction("\t/***/", "", null, null); - support.testIndentAction("\t/*******/", "", null, null); - support.testIndentAction("\t/** * * * * */", "", null, null); - support.testIndentAction("\t/** */", "", null, null); - support.testIndentAction("\t/** asdfg */", "", null, null); - support.testIndentAction("\t/* asdfg */", "", null, null); - support.testIndentAction("\t/* asdfg */", "", null, null); - support.testIndentAction("\t/** asdfg */", "", null, null); - support.testIndentAction("*/", "", null, null); - support.testIndentAction("\t/*", "", null, null); - support.testIndentAction("\t*", "", null, null); - support.testIndentAction("\t *", "", IndentAction.None, "* "); - support.testIndentAction("\t */", "", IndentAction.None, null, 1); - support.testIndentAction("\t * */", "", IndentAction.None, null, 1); - support.testIndentAction("\t * * / * / * / */", "", null, null); - support.testIndentAction("\t * ", "", IndentAction.None, "* "); - support.testIndentAction(" * ", "", IndentAction.None, "* "); - support.testIndentAction(" * asdfsfagadfg", "", IndentAction.None, "* "); - support.testIndentAction(" * asdfsfagadfg * * * ", "", IndentAction.None, "* "); - support.testIndentAction(" * /*", "", IndentAction.None, "* "); - support.testIndentAction(" * asdfsfagadfg * / * / * /", "", IndentAction.None, "* "); - support.testIndentAction(" * asdfsfagadfg * / * / * /*", "", IndentAction.None, "* "); - support.testIndentAction(" */", "", IndentAction.None, null, 1); - support.testIndentAction("\t */", "", IndentAction.None, null, 1); - support.testIndentAction("\t\t */", "", IndentAction.None, null, 1); - support.testIndentAction(" */", "", IndentAction.None, null, 1); - support.testIndentAction(" */", "", IndentAction.None, null, 1); - support.testIndentAction("\t */", "", IndentAction.None, null, 1); - support.testIndentAction( - " *--------------------------------------------------------------------------------------------*/", "", - IndentAction.None, null, 1); - } - - private class RegExpRulesTest extends OnEnterSupport { - - public RegExpRulesTest() { - super(null, - Arrays.asList( - new OnEnterRule("^\\s*\\/\\*\\*(?!\\/)([^\\*]|\\*(?!\\/))*$", "^\\s*\\*\\/$", - new EnterAction(IndentAction.IndentOutdent).setAppendText(" * ")), - new OnEnterRule("^\\s*\\/\\*\\*(?!\\/)([^\\*]|\\*(?!\\/))*$", null, - new EnterAction(IndentAction.None).setAppendText(" * ")), - new OnEnterRule("^(\\t|(\\ \\ ))*\\ \\*(\\ ([^\\*]|\\*(?!\\/))*)?$", null, - new EnterAction(IndentAction.None).setAppendText("* ")), - new OnEnterRule("^(\\t|(\\ \\ ))*\\ \\*\\/\\s*$", null, - new EnterAction(IndentAction.None).setRemoveText(1)), - new OnEnterRule("^(\\t|(\\ \\ ))*\\ \\*[^/]*\\*\\/\\s*$", null, - new EnterAction(IndentAction.None).setRemoveText(1)))); - } - - public void testIndentAction(String beforeText, String afterText, IndentAction expectedIndentAction, - String expectedAppendText) { - testIndentAction(beforeText, afterText, expectedIndentAction, expectedAppendText, 0); - } - - public void testIndentAction(String beforeText, String afterText, IndentAction expectedIndentAction, - String expectedAppendText, int removeText) { - EnterAction actual = super.onEnter("", beforeText, afterText); - if (expectedIndentAction == null) { - assertNull(actual, "isNull:" + beforeText); - } else { - assertNotNull(actual, "isNotNull:" + beforeText); - assertEquals(expectedIndentAction, actual.getIndentAction(), "indentAction:" + beforeText); - if (expectedAppendText != null) { - assertEquals(expectedAppendText, actual.getAppendText(), "appendText:" + beforeText); - } - if (removeText != 0) { - assertEquals(removeText, actual.getRemoveText(), "removeText:" + beforeText); - } - } - } - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.languageconfiguration.internal.supports; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.languageconfiguration.internal.supports.EnterAction.IndentAction; +import org.junit.jupiter.api.Test; + +/** + * {@link OnEnterSupport} tests. + * + */ +public class OnEnterSupportTest { + + @Test + public void useBrackets() { + UseBracketsTest support = new UseBracketsTest(); + + support.testIndentAction("a", "", IndentAction.None); + support.testIndentAction("", "b", IndentAction.None); + support.testIndentAction("(", "b", IndentAction.Indent); + support.testIndentAction("a", ")", IndentAction.None); + support.testIndentAction("begin", "ending", IndentAction.Indent); + support.testIndentAction("abegin", "end", IndentAction.None); + support.testIndentAction("begin", ")", IndentAction.Indent); + support.testIndentAction("begin", "end", IndentAction.IndentOutdent); + support.testIndentAction("begin ", " end", IndentAction.IndentOutdent); + support.testIndentAction(" begin", "end//as", IndentAction.IndentOutdent); + support.testIndentAction("(", ")", IndentAction.IndentOutdent); + support.testIndentAction("( ", ")", IndentAction.IndentOutdent); + support.testIndentAction("a(", ")b", IndentAction.IndentOutdent); + + support.testIndentAction("(", "", IndentAction.Indent); + support.testIndentAction("(", "foo", IndentAction.Indent); + support.testIndentAction("begin", "foo", IndentAction.Indent); + support.testIndentAction("begin", "", IndentAction.Indent); + } + + private class UseBracketsTest extends OnEnterSupport { + + public UseBracketsTest() { + super(Arrays.asList(new CharacterPair("(", ")"), new CharacterPair("begin", "end")), null); + } + + public void testIndentAction(String beforeText, String afterText, IndentAction expected) { + EnterAction actual = super.onEnter("", beforeText, afterText); + if (expected == IndentAction.None) { + assertNull(actual); + } else { + assertNotNull(actual); + assertEquals(expected, actual.getIndentAction()); + } + } + } + + @Test + public void regExpRules() { + RegExpRulesTest support = new RegExpRulesTest(); + + support.testIndentAction("\t/**", " */", IndentAction.IndentOutdent, " * "); + support.testIndentAction("\t/**", "", IndentAction.None, " * "); + support.testIndentAction("\t/** * / * / * /", "", IndentAction.None, " * "); + support.testIndentAction("\t/** /*", "", IndentAction.None, " * "); + support.testIndentAction("/**", "", IndentAction.None, " * "); + support.testIndentAction("\t/**/", "", null, null); + support.testIndentAction("\t/***/", "", null, null); + support.testIndentAction("\t/*******/", "", null, null); + support.testIndentAction("\t/** * * * * */", "", null, null); + support.testIndentAction("\t/** */", "", null, null); + support.testIndentAction("\t/** asdfg */", "", null, null); + support.testIndentAction("\t/* asdfg */", "", null, null); + support.testIndentAction("\t/* asdfg */", "", null, null); + support.testIndentAction("\t/** asdfg */", "", null, null); + support.testIndentAction("*/", "", null, null); + support.testIndentAction("\t/*", "", null, null); + support.testIndentAction("\t*", "", null, null); + support.testIndentAction("\t *", "", IndentAction.None, "* "); + support.testIndentAction("\t */", "", IndentAction.None, null, 1); + support.testIndentAction("\t * */", "", IndentAction.None, null, 1); + support.testIndentAction("\t * * / * / * / */", "", null, null); + support.testIndentAction("\t * ", "", IndentAction.None, "* "); + support.testIndentAction(" * ", "", IndentAction.None, "* "); + support.testIndentAction(" * asdfsfagadfg", "", IndentAction.None, "* "); + support.testIndentAction(" * asdfsfagadfg * * * ", "", IndentAction.None, "* "); + support.testIndentAction(" * /*", "", IndentAction.None, "* "); + support.testIndentAction(" * asdfsfagadfg * / * / * /", "", IndentAction.None, "* "); + support.testIndentAction(" * asdfsfagadfg * / * / * /*", "", IndentAction.None, "* "); + support.testIndentAction(" */", "", IndentAction.None, null, 1); + support.testIndentAction("\t */", "", IndentAction.None, null, 1); + support.testIndentAction("\t\t */", "", IndentAction.None, null, 1); + support.testIndentAction(" */", "", IndentAction.None, null, 1); + support.testIndentAction(" */", "", IndentAction.None, null, 1); + support.testIndentAction("\t */", "", IndentAction.None, null, 1); + support.testIndentAction( + " *--------------------------------------------------------------------------------------------*/", "", + IndentAction.None, null, 1); + } + + private class RegExpRulesTest extends OnEnterSupport { + + public RegExpRulesTest() { + super(null, + List.of( + new OnEnterRule("^\\s*\\/\\*\\*(?!\\/)([^\\*]|\\*(?!\\/))*$", "^\\s*\\*\\/$", + new EnterAction(IndentAction.IndentOutdent).setAppendText(" * ")), + new OnEnterRule("^\\s*\\/\\*\\*(?!\\/)([^\\*]|\\*(?!\\/))*$", null, + new EnterAction(IndentAction.None).setAppendText(" * ")), + new OnEnterRule("^(\\t|(\\ \\ ))*\\ \\*(\\ ([^\\*]|\\*(?!\\/))*)?$", null, + new EnterAction(IndentAction.None).setAppendText("* ")), + new OnEnterRule("^(\\t|(\\ \\ ))*\\ \\*\\/\\s*$", null, + new EnterAction(IndentAction.None).setRemoveText(1)), + new OnEnterRule("^(\\t|(\\ \\ ))*\\ \\*[^/]*\\*\\/\\s*$", null, + new EnterAction(IndentAction.None).setRemoveText(1)))); + } + + public void testIndentAction(String beforeText, String afterText, @Nullable IndentAction expectedIndentAction, + @Nullable String expectedAppendText) { + testIndentAction(beforeText, afterText, expectedIndentAction, expectedAppendText, 0); + } + + public void testIndentAction(String beforeText, String afterText, @Nullable IndentAction expectedIndentAction, + @Nullable String expectedAppendText, int removeText) { + EnterAction actual = super.onEnter("", beforeText, afterText); + if (expectedIndentAction == null) { + assertNull(actual, "isNull:" + beforeText); + } else { + assertNotNull(actual, "isNotNull:" + beforeText); + assertEquals(expectedIndentAction, actual.getIndentAction(), "indentAction:" + beforeText); + if (expectedAppendText != null) { + assertEquals(expectedAppendText, actual.getAppendText(), "appendText:" + beforeText); + } + if (removeText != 0) { + assertEquals(removeText, actual.getRemoveText(), "removeText:" + beforeText); + } + } + } + } +} diff --git a/org.eclipse.tm4e.languageconfiguration/src/test/java/org/eclipse/tm4e/languageconfiguration/internal/supports/ParsingTest.java b/org.eclipse.tm4e.languageconfiguration/src/test/java/org/eclipse/tm4e/languageconfiguration/internal/supports/ParsingTest.java index 652ca29fb..9344b40db 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/test/java/org/eclipse/tm4e/languageconfiguration/internal/supports/ParsingTest.java +++ b/org.eclipse.tm4e.languageconfiguration/src/test/java/org/eclipse/tm4e/languageconfiguration/internal/supports/ParsingTest.java @@ -1,27 +1,43 @@ /********************************************************************* -* Copyright (c) 2018 Red Hat Inc., and others -* -* This program and the accompanying materials are made -* available under the terms of the Eclipse Public License 2.0 -* which is available at https://www.eclipse.org/legal/epl-2.0/ -* -* SPDX-License-Identifier: EPL-2.0 -**********************************************************************/ + * Copyright (c) 2018 Red Hat Inc., and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + **********************************************************************/ package org.eclipse.tm4e.languageconfiguration.internal.supports; import static org.junit.jupiter.api.Assertions.assertNotNull; +import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tm4e.languageconfiguration.internal.LanguageConfiguration; import org.junit.jupiter.api.Test; public class ParsingTest { + @Nullable + private LanguageConfiguration loadLanguageConfiguration(String path) throws IOException { + try (InputStream is = getClass().getResourceAsStream(path)) { + assertNotNull(is); + return LanguageConfiguration.load(new InputStreamReader(is)); + } + } + @Test - public void testCanLoadRustLanguageConfig() throws Exception { - LanguageConfiguration languageConfiguration = LanguageConfiguration.load(new InputStreamReader(getClass().getResourceAsStream("/rust-language-configuration.json"))); + public void testCanLoadPhpLanguageConfig() throws Exception { + final var languageConfiguration = loadLanguageConfiguration("/php-language-configuration.json"); assertNotNull(languageConfiguration); } + @Test + public void testCanLoadRustLanguageConfig() throws Exception { + final var languageConfiguration = loadLanguageConfiguration("/rust-language-configuration.json"); + assertNotNull(languageConfiguration); + } } diff --git a/org.eclipse.tm4e.languageconfiguration/src/test/resources/php-language-configuration.json b/org.eclipse.tm4e.languageconfiguration/src/test/resources/php-language-configuration.json new file mode 100644 index 000000000..e02f24bd1 --- /dev/null +++ b/org.eclipse.tm4e.languageconfiguration/src/test/resources/php-language-configuration.json @@ -0,0 +1,81 @@ +{ + "comments": { + "lineComment": "//", // "#" + "blockComment": [ "/*", "*/" ] + }, + "brackets": [ + ["{", "}"], + ["[", "]"], + ["(", ")"] + ], + "autoClosingPairs": [ + { "open": "{", "close": "}", "notIn": ["string"] }, + { "open": "[", "close": "]", "notIn": ["string"] }, + { "open": "(", "close": ")", "notIn": ["string"] }, + { "open": "'", "close": "'", "notIn": ["string", "comment"] }, + { "open": "\"", "close": "\"", "notIn": ["string", "comment"] }, + { "open": "/**", "close": " */", "notIn": ["string"] } + ], + "surroundingPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["'", "'"], + ["\"", "\""], + ["`", "`"] + ], + "indentationRules": { + "increaseIndentPattern": "({(?!.*}).*|\\(|\\[|((else(\\s)?)?if|else|for(each)?|while|switch|case).*:)\\s*((/[/*].*|)?$|\\?>)", + "decreaseIndentPattern": "^(.*\\*\\/)?\\s*((\\})|(\\)+[;,])|(\\]\\)*[;,])|\\b(else:)|\\b((end(if|for(each)?|while|switch));))" + }, + "folding": { + "markers": { + "start": "^\\s*(#|\/\/)region\\b", + "end": "^\\s*(#|\/\/)endregion\\b" + } + }, + "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\-\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)", + "onEnterRules": [ + { + // e.g. /** | */ + "beforeText": "^\\s*\\/\\*\\*(?!\\/)([^\\*]|\\*(?!\\/))*$", + "afterText": "^\\s*\\*\\/$", + "action": { + "indent": "indentOutdent", + "appendText": " * " + } + }, + { + // e.g. /** ...| + "beforeText": "^\\s*\\/\\*\\*(?!\\/)([^\\*]|\\*(?!\\/))*$", + "action": { + "indent": "none", + "appendText": " * " + } + }, + { + // e.g. * ...| + "beforeText": "^(\\t|(\\ \\ ))*\\ \\*(\\ ([^\\*]|\\*(?!\\/))*)?$", + "action": { + "indent": "none", + "appendText": "* " + } + }, + { + // e.g. */| + "beforeText": "^(\\t|(\\ \\ ))*\\ \\*\\/\\s*$", + "action": { + "indent": "none", + "removeText": 1 + } + }, + { + // e.g. *-----*/| + "beforeText": "^(\\t|(\\ \\ ))*\\ \\*[^/]*\\*\\/\\s*$", + "action": { + "indent": "none", + "removeText": 1 + } + } + ] +} diff --git a/org.eclipse.tm4e.markdown/.classpath b/org.eclipse.tm4e.markdown/.classpath index 0bf6f096c..71f21812a 100644 --- a/org.eclipse.tm4e.markdown/.classpath +++ b/org.eclipse.tm4e.markdown/.classpath @@ -6,7 +6,22 @@ - - + + + + + + + + + + + + + + + + + diff --git a/org.eclipse.tm4e.markdown/.gitignore b/org.eclipse.tm4e.markdown/.gitignore deleted file mode 100644 index 934e0e06f..000000000 --- a/org.eclipse.tm4e.markdown/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/bin -/target diff --git a/org.eclipse.tm4e.markdown/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.tm4e.markdown/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..6b99f88fc --- /dev/null +++ b/org.eclipse.tm4e.markdown/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,518 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.APILeak=warning +org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning +org.eclipse.jdt.core.compiler.problem.fallthroughCase=info +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=info +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=info +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=enabled +org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=11 +org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false +org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false +org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter=0 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type=49 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assertion_message=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0 +org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_record_components=16 +org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_type_annotations=0 +org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0 +org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch=0 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_constructor=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false +org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true +org.eclipse.jdt.core.formatter.comment.format_block_comments=false +org.eclipse.jdt.core.formatter.comment.format_header=true +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.indent_tag_description=false +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=120 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_not_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false +org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.text_block_indentation=0 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false +org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true +org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true +org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true +org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true +org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/org.eclipse.tm4e.markdown/META-INF/MANIFEST.MF b/org.eclipse.tm4e.markdown/META-INF/MANIFEST.MF index 9f7a22989..96c535939 100644 --- a/org.eclipse.tm4e.markdown/META-INF/MANIFEST.MF +++ b/org.eclipse.tm4e.markdown/META-INF/MANIFEST.MF @@ -4,11 +4,12 @@ Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-Localization: plugin Bundle-SymbolicName: org.eclipse.tm4e.markdown;singleton:=true -Bundle-Version: 0.3.5.qualifier +Bundle-Version: 0.3.6.qualifier Require-Bundle: org.eclipse.core.runtime, - org.eclipse.tm4e.core, - org.eclipse.tm4e.registry, - org.eclipse.tm4e.ui + org.eclipse.tm4e.core;bundle-version="0.4.4", + org.eclipse.tm4e.registry;bundle-version="0.5.1", + org.eclipse.tm4e.ui;bundle-version="0.5.1", + com.google.guava;bundle-version="30.1.0" Bundle-RequiredExecutionEnvironment: JavaSE-11 Export-Package: org.eclipse.tm4e.markdown, org.eclipse.tm4e.markdown.marked diff --git a/org.eclipse.tm4e.markdown/build.properties b/org.eclipse.tm4e.markdown/build.properties index 065c68847..0a9f3a653 100644 --- a/org.eclipse.tm4e.markdown/build.properties +++ b/org.eclipse.tm4e.markdown/build.properties @@ -4,3 +4,9 @@ bin.includes = META-INF/,\ .,\ plugin.properties,\ about.html + +# https://codeiseasy.wordpress.com/2013/03/08/tycho-and-jdt-null-analysis/ +# JDT Null Analysis for Eclipse +additional.bundles = org.eclipse.jdt.annotation +# JDT Null Analysis types for Tycho +jars.extra.classpath = platform:/plugin/org.eclipse.jdt.annotation diff --git a/org.eclipse.tm4e.markdown/pom.xml b/org.eclipse.tm4e.markdown/pom.xml index de99f8992..b9f0ba6d3 100644 --- a/org.eclipse.tm4e.markdown/pom.xml +++ b/org.eclipse.tm4e.markdown/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.eclipse.tm4e.markdown eclipse-plugin - 0.3.5-SNAPSHOT + 0.3.6-SNAPSHOT org.eclipse org.eclipse.tm4e diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/TMHTMLRenderer.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/TMHTMLRenderer.java index 42b6b4d94..1127bf592 100644 --- a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/TMHTMLRenderer.java +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/TMHTMLRenderer.java @@ -1,116 +1,117 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.markdown; - -import java.util.List; - -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.tm4e.core.grammar.IGrammar; -import org.eclipse.tm4e.core.model.ITokenizationSupport; -import org.eclipse.tm4e.core.model.LineTokens; -import org.eclipse.tm4e.core.model.TMState; -import org.eclipse.tm4e.core.model.TMToken; -import org.eclipse.tm4e.core.model.Tokenizer; -import org.eclipse.tm4e.markdown.marked.HTMLRenderer; -import org.eclipse.tm4e.markdown.marked.Helpers; -import org.eclipse.tm4e.registry.TMEclipseRegistryPlugin; - -public class TMHTMLRenderer extends HTMLRenderer { - - private final String defaultLang; - - public TMHTMLRenderer(String defaultLang) { - this.defaultLang = defaultLang; - } - - @Override - public void code(String code, String lang, boolean escaped) { - IGrammar grammar = lang == null ? getDefaultGrammar() : getGrammar(lang); - if (grammar == null) { - super.code(code, lang, escaped); - } else { - ITokenizationSupport tokenizationSupport = new Tokenizer(grammar); - html.append("
    "); - tokenizeLines(code, tokenizationSupport); - html.append("
    "); - } - } - - private void tokenizeLines(String text, ITokenizationSupport tokenizationSupport) { - String[] lines = text.split("\r\n|\r|\n"); - TMState currentState = tokenizationSupport.getInitialState(); - for (int i = 0; i < lines.length; i++) { - currentState = tokenizeLine(lines[i], tokenizationSupport, currentState); - - // Keep new lines - if (i < lines.length - 1) { - emitNewLine(); - } - } - } - - private void emitNewLine() { - html.append("
    "); - } - - private TMState tokenizeLine(String line, ITokenizationSupport tokenizationSupport, TMState startState) { - LineTokens tokenized = tokenizationSupport.tokenize(line, startState); - TMState endState = tokenized.getEndState(); - List tokens = tokenized.getTokens(); - int offset = 0; - String tokenText; - - // For each token inject spans with proper class names based on token - // type - for (int j = 0; j < tokens.size(); j++) { - TMToken token = tokens.get(j); - - // Tokens only provide a startIndex from where they are valid from. - // As such, we need to - // look ahead the value of the token by advancing until the next - // tokens start inex or the - // end of the line. - if (j < tokens.size() - 1) { - tokenText = line.substring(offset, tokens.get(j + 1).startIndex); - offset = tokens.get(j + 1).startIndex; - } else { - tokenText = line.substring(offset); - } - - String className = "token"; - String safeType = token.type.replaceAll("[^a-z0-9\\-]", " "); - if (safeType.length() > 0) { - className += ' ' + safeType; - } - - html.append(""); - html.append(Helpers.escape(tokenText)); - html.append(""); - // emitToken(className, tokenText); - } - - return endState; - } - - protected IGrammar getDefaultGrammar() { - return getGrammar(defaultLang); - } - - protected IGrammar getGrammar(String lang) { - IContentType[] contentTypes = Platform.getContentTypeManager().findContentTypesFor("x." + lang); - return TMEclipseRegistryPlugin.getGrammarRegistryManager().getGrammarFor(contentTypes); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.markdown; + +import java.util.List; + +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.grammar.IGrammar; +import org.eclipse.tm4e.core.model.ITokenizationSupport; +import org.eclipse.tm4e.core.model.LineTokens; +import org.eclipse.tm4e.core.model.TMState; +import org.eclipse.tm4e.core.model.TMToken; +import org.eclipse.tm4e.core.model.Tokenizer; +import org.eclipse.tm4e.markdown.marked.HTMLRenderer; +import org.eclipse.tm4e.markdown.marked.Helpers; +import org.eclipse.tm4e.registry.TMEclipseRegistryPlugin; + +public class TMHTMLRenderer extends HTMLRenderer { + + private final String defaultLang; + + public TMHTMLRenderer(final String defaultLang) { + this.defaultLang = defaultLang; + } + + @Override + public void code(final String code, @Nullable final String lang, final boolean escaped) { + final IGrammar grammar = lang == null ? getDefaultGrammar() : getGrammar(lang); + if (grammar == null) { + super.code(code, lang, escaped); + } else { + final ITokenizationSupport tokenizationSupport = new Tokenizer(grammar); + html.append("
    "); + tokenizeLines(code, tokenizationSupport); + html.append("
    "); + } + } + + private void tokenizeLines(final String text, final ITokenizationSupport tokenizationSupport) { + final String[] lines = text.split("\r\n|\r|\n"); + TMState currentState = tokenizationSupport.getInitialState(); + for (int i = 0; i < lines.length; i++) { + currentState = tokenizeLine(lines[i], tokenizationSupport, currentState); + + // Keep new lines + if (i < lines.length - 1) { + emitNewLine(); + } + } + } + + private void emitNewLine() { + html.append("
    "); + } + + @Nullable + private TMState tokenizeLine(final String line, final ITokenizationSupport tokenizationSupport, @Nullable final TMState startState) { + final LineTokens tokenized = tokenizationSupport.tokenize(line, startState); + final TMState endState = tokenized.getEndState(); + final List tokens = tokenized.getTokens(); + int offset = 0; + String tokenText; + + // For each token inject spans with proper class names based on token type + for (int j = 0; j < tokens.size(); j++) { + final TMToken token = tokens.get(j); + + // Tokens only provide a startIndex from where they are valid from. + // As such, we need to look ahead the value of the token by advancing until the next + // tokens start inex or the end of the line. + if (j < tokens.size() - 1) { + tokenText = line.substring(offset, tokens.get(j + 1).startIndex); + offset = tokens.get(j + 1).startIndex; + } else { + tokenText = line.substring(offset); + } + + String className = "token"; + final String safeType = token.type.replaceAll("[^a-z0-9\\-]", " "); + if (!safeType.isEmpty()) { + className += ' ' + safeType; + } + + html.append(""); + html.append(Helpers.htmlEscape(tokenText)); + html.append(""); + // emitToken(className, tokenText); + } + + return endState; + } + + @Nullable + protected IGrammar getDefaultGrammar() { + return getGrammar(defaultLang); + } + + @Nullable + protected IGrammar getGrammar(final String lang) { + final IContentType[] contentTypes = Platform.getContentTypeManager().findContentTypesFor("x." + lang); + return TMEclipseRegistryPlugin.getGrammarRegistryManager().getGrammarFor(contentTypes); + } +} diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/TMMarkdownPlugin.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/TMMarkdownPlugin.java index b8dff4ee2..a9398de4c 100644 --- a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/TMMarkdownPlugin.java +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/TMMarkdownPlugin.java @@ -1,40 +1,42 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.markdown; - -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - -/** - * OSGi Activator for TextMate Markdown bundle. - * - */ -public class TMMarkdownPlugin implements BundleActivator { - - public static final String PLUGIN_ID = "org.eclipse.tm4e.markdown"; - - private static BundleContext context; - - static BundleContext getContext() { - return context; - } - - @Override - public void start(BundleContext bundleContext) throws Exception { - TMMarkdownPlugin.context = bundleContext; - } - - @Override - public void stop(BundleContext bundleContext) throws Exception { - TMMarkdownPlugin.context = null; - } + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.markdown; + +import org.eclipse.jdt.annotation.Nullable; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +/** + * OSGi Activator for TextMate Markdown bundle. + */ +public class TMMarkdownPlugin implements BundleActivator { + + public static final String PLUGIN_ID = "org.eclipse.tm4e.markdown"; + + @Nullable + private static BundleContext context; + + @Nullable + static BundleContext getContext() { + return context; + } + + @Override + public void start(@Nullable final BundleContext bundleContext) throws Exception { + TMMarkdownPlugin.context = bundleContext; + } + + @Override + public void stop(@Nullable final BundleContext bundleContext) throws Exception { + TMMarkdownPlugin.context = null; + } } \ No newline at end of file diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/BlockRules.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/BlockRules.java index a2465b607..96edbefcc 100644 --- a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/BlockRules.java +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/BlockRules.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,107 +11,111 @@ * Initial license: MIT * * Contributors: - * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.markdown.marked; - -public class BlockRules { - - private static final String _tag = "(?!(?:" + "a|em|strong|small|s|cite|q|dfn|abbr|data|time|code" - + "|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo" - + "|span|br|wbr|ins|del|img)\\b)\\w+(?!:\\/|[^\\w\\s@]*@)\\b"; - - public static BlockRules normal = normal(); - public static BlockRules gfm = gfm(); - public static BlockRules tables = tables(); - - public final RegExp newline; - public final RegExp code; - public final RegExp fences; - public final RegExp hr; - public final RegExp heading; - public final RegExp nptable; - public final RegExp lheading; - public final RegExp blockquote; - public final RegExp list; - public final RegExp html; - public final RegExp def; - public final RegExp table; - public final RegExp paragraph; - public final RegExp text; - public final RegExp bullet; - public final RegExp item; - - public BlockRules(RegExp newline, RegExp code, RegExp fences, RegExp hr, RegExp heading, RegExp nptable, - RegExp lheading, RegExp blockquote, RegExp list, RegExp html, RegExp def, RegExp table, RegExp paragraph, - RegExp text, RegExp bullet, RegExp item) { - this.newline = newline; - this.code = code; - this.fences = fences; - this.hr = hr; - this.heading = heading; - this.nptable = nptable; - this.lheading = lheading; - this.blockquote = blockquote; - this.list = list; - this.html = html; - this.def = def; - this.table = table; - this.paragraph = paragraph; - this.text = text; - this.bullet = bullet; - this.item = item; - } - - private static BlockRules block() { - RegExp newline = new RegExp("^\\n+"); - RegExp code = new RegExp("^( {4}[^\\n]+\\n*)+/"); - RegExp fences = new RegExp(""); - RegExp hr = new RegExp("^( *[-*_]){3,} *(?:\\n+|$)"); - RegExp heading = new RegExp("^ *(#{1,6}) *([^\\n]+?) *#* *(?:\\n+|$)"); - RegExp nptable = new RegExp(""); - RegExp lheading = new RegExp("^([^\\n]+)\\n *(=|-){2,} *(?:\\n+|$)"); - RegExp blockquote = new RegExp("^( *>[^\\n]+(\\n(?!def)[^\\n]+)*\\n*)+"); - RegExp list = new RegExp("^( *)(bull) [\\s\\S]+?(?:hr|def|\\n{2,}(?! )(?!\\1bull )\\n*|\\s*$)"); - RegExp html = new RegExp("^ *(?:comment *(?:\\n|\\s*$)|closed *(?:\\n{2,}|\\s*$)|closing *(?:\\n{2,}|\\s*$))"); - RegExp def = new RegExp("^ *\\[([^\\]]+)\\]: *]+)>?(?: +[\"(]([^\\n]+)[\")])? *(?:\\n+|$)"); - RegExp table = RegExp.noop(); - RegExp paragraph = new RegExp("^((?:[^\\n]+\\n?(?!hr|heading|lheading|blockquote|tag|def))+)\\n*"); - RegExp text = new RegExp("^[^\\n]+"); - RegExp bullet = new RegExp("(?:[*+-]|\\d+\\.)"); - RegExp item = new RegExp("^( *)(bull) [^\\n]*(?:\\n(?!\\1bull )[^\\n]*)*"); - - item.replaceAll("bull", bullet); - list.replaceAll("bull", bullet).replace("hr", "\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))").replace("def", - "\\n+(?=" + def.source + ")"); - blockquote.replace("def", def); - paragraph.replace("hr", hr).replace("heading", heading).replace("lheading", lheading) - .replace("blockquote", blockquote).replace("tag", "<" + _tag).replace("def", def); - return new BlockRules(newline, code, fences, hr, heading, nptable, lheading, blockquote, list, html, def, table, - paragraph, text, bullet, item); - } - - private static BlockRules normal() { - return block(); - } - - private static BlockRules gfm() { - BlockRules gfm = normal(); - gfm.fences.source = "^ *(`{3,}|~{3,})[ \\.]*(\\S+)? *\\n([\\s\\S]*?)\\s*\\1 *(?:\\n+|$)"; - // gfm.paragraph.source = "^"; - gfm.heading.source = "^ *(#{1,6}) +([^\\n]+?) *#* *(?:\\n+|$)"; - String pattern = "(?!" + gfm.fences.source.replaceFirst("\\\\1", "\\\\2") + "|" - + gfm.list.source.replaceFirst("\\\\1", "\\\\3") + "|"; - //pattern = pattern.replaceAll("\\\"", "\\\\\""); - //pattern = pattern.replaceAll("[$]", "\\\\\\$"); - gfm.paragraph.replace("\\(\\?\\!", pattern); - return gfm; - } - - private static BlockRules tables() { - BlockRules tables = gfm(); - - return tables; - } -} + * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.markdown.marked; + +public class BlockRules { + + private static final String _tag = "(?!(?:" + "a|em|strong|small|s|cite|q|dfn|abbr|data|time|code" + + "|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo" + + "|span|br|wbr|ins|del|img)\\b)\\w+(?!:\\/|[^\\w\\s@]*@)\\b"; + + public static BlockRules normal = normal(); + public static BlockRules gfm = gfm(); + public static BlockRules tables = tables(); + + public final RegExp newline; + public final RegExp code; + public final RegExp fences; + public final RegExp hr; + public final RegExp heading; + public final RegExp nptable; + public final RegExp lheading; + public final RegExp blockquote; + public final RegExp list; + public final RegExp html; + public final RegExp def; + public final RegExp table; + public final RegExp paragraph; + public final RegExp text; + public final RegExp bullet; + public final RegExp item; + + public BlockRules(final RegExp newline, final RegExp code, final RegExp fences, final RegExp hr, + final RegExp heading, final RegExp nptable, + final RegExp lheading, final RegExp blockquote, final RegExp list, final RegExp html, final RegExp def, + final RegExp table, final RegExp paragraph, + final RegExp text, final RegExp bullet, final RegExp item) { + this.newline = newline; + this.code = code; + this.fences = fences; + this.hr = hr; + this.heading = heading; + this.nptable = nptable; + this.lheading = lheading; + this.blockquote = blockquote; + this.list = list; + this.html = html; + this.def = def; + this.table = table; + this.paragraph = paragraph; + this.text = text; + this.bullet = bullet; + this.item = item; + } + + private static BlockRules block() { + final RegExp newline = new RegExp("^\\n+"); + final RegExp code = new RegExp("^( {4}[^\\n]+\\n*)+/"); + final RegExp fences = new RegExp(""); + final RegExp hr = new RegExp("^( *[-*_]){3,} *(?:\\n+|$)"); + final RegExp heading = new RegExp("^ *(#{1,6}) *([^\\n]+?) *#* *(?:\\n+|$)"); + final RegExp nptable = new RegExp(""); + final RegExp lheading = new RegExp("^([^\\n]+)\\n *(=|-){2,} *(?:\\n+|$)"); + final RegExp blockquote = new RegExp("^( *>[^\\n]+(\\n(?!def)[^\\n]+)*\\n*)+"); + final RegExp list = new RegExp("^( *)(bull) [\\s\\S]+?(?:hr|def|\\n{2,}(?! )(?!\\1bull )\\n*|\\s*$)"); + final RegExp html = new RegExp("^ *(?:comment *(?:\\n|\\s*$)|closed *(?:\\n{2,}|\\s*$)|closing *(?:\\n{2,}|\\s*$))"); + final RegExp def = new RegExp("^ *\\[([^\\]]+)\\]: *]+)>?(?: +[\"(]([^\\n]+)[\")])? *(?:\\n+|$)"); + final RegExp table = RegExp.noop(); + final RegExp paragraph = new RegExp("^((?:[^\\n]+\\n?(?!hr|heading|lheading|blockquote|tag|def))+)\\n*"); + final RegExp text = new RegExp("^[^\\n]+"); + final RegExp bullet = new RegExp("(?:[*+-]|\\d+\\.)"); + final RegExp item = new RegExp("^( *)(bull) [^\\n]*(?:\\n(?!\\1bull )[^\\n]*)*"); + + item.replaceAll("bull", bullet); + list.replaceAll("bull", bullet).replace("hr", "\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))").replace("def", + "\\n+(?=" + def.source + ")"); + blockquote.replace("def", def); + paragraph.replace("hr", hr).replace("heading", heading).replace("lheading", lheading) + .replace("blockquote", blockquote).replace("tag", "<" + _tag).replace("def", def); + return new BlockRules(newline, code, fences, hr, heading, nptable, lheading, blockquote, list, html, def, table, + paragraph, text, bullet, item); + } + + private static BlockRules normal() { + return block(); + } + + private static BlockRules gfm() { + final BlockRules gfm = normal(); + final var source = "^ *(`{3,}|~{3,})[ \\.]*(\\S+)? *\\n([\\s\\S]*?)\\s*\\1 *(?:\\n+|$)"; + gfm.fences.source = source; + // gfm.paragraph.source = "^"; + gfm.heading.source = "^ *(#{1,6}) +([^\\n]+?) *#* *(?:\\n+|$)"; + final String pattern = "(?!" + + source.replaceFirst("\\\\1", "\\\\2") + "|" + + source.replaceFirst("\\\\1", "\\\\3") + + "|"; + // pattern = pattern.replaceAll("\\\"", "\\\\\""); + // pattern = pattern.replaceAll("[$]", "\\\\\\$"); + gfm.paragraph.replace("\\(\\?\\!", pattern); + return gfm; + } + + private static BlockRules tables() { + final BlockRules tables = gfm(); + return tables; + } +} diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/HTMLRenderer.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/HTMLRenderer.java index ec0f2789d..4e063abc8 100644 --- a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/HTMLRenderer.java +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/HTMLRenderer.java @@ -13,163 +13,165 @@ * Contributors: * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.markdown.marked; - -import static org.eclipse.tm4e.markdown.marked.Helpers.escape; - -public class HTMLRenderer implements IRenderer { - - protected final StringBuilder html; - - public HTMLRenderer() { - this(new StringBuilder()); - } - - public HTMLRenderer(StringBuilder html) { - this.html = html; - } - - @Override - public void code(String code, String lang, boolean escaped) { - if (lang == null) { - html.append("
    ");
    -			html.append(escaped ? code : escape(code, true));
    -			html.append("\n
    "); - } else { - html.append("
    ");
    -			html.append(escaped ? code : escape(code, true));
    -			html.append("\n
    "); - } - } - - @Override - public void blockquote(String quote) { - // TODO Auto-generated method stub - - } - - @Override - public void html(String html) { - // TODO Auto-generated method stub - - } - - @Override - public void heading(String text, int level, String raw) { - html.append(""); - html.append(text); - html.append("\n"); - } - - @Override - public void hr() { - html.append("
    \n"); - } - - @Override - public void list(String body, boolean ordered) { - // TODO Auto-generated method stub - - } - - @Override - public void listitem(String text) { - // TODO Auto-generated method stub - - } - - @Override - public void startParagraph() { - html.append("

    "); - } - - @Override - public void endParagraph() { - html.append("

    \n"); - } - - @Override - public void table(String header, String body) { - // TODO Auto-generated method stub - - } - - @Override - public void tablerow(String content) { - // TODO Auto-generated method stub - - } - - @Override - public void tablecell(String content, String flags) { - // TODO Auto-generated method stub - - } - - @Override - public void startEm() { - html.append(""); - } - - @Override - public void endEm() { - html.append(""); - } - - @Override - public void startStrong() { - html.append(""); - } - - @Override - public void endStrong() { - html.append(""); - } - - @Override - public void codespan(String text) { - html.append(""); - html.append(text); - html.append(""); - } - - @Override - public void br() { - // TODO Auto-generated method stub - - } - - @Override - public void del(String text) { - // TODO Auto-generated method stub - - } - - @Override - public void link(String href, String title, String text) { - // TODO Auto-generated method stub - - } - - @Override - public void image(String href, String title, String text) { - // TODO Auto-generated method stub - - } - - @Override - public void text(String text) { - html.append(text); - } - - @Override - public String toString() { - return html.toString(); - } -} + */ +package org.eclipse.tm4e.markdown.marked; + +import static org.eclipse.tm4e.markdown.marked.Helpers.htmlEscape; + +import org.eclipse.jdt.annotation.Nullable; + +public class HTMLRenderer implements IRenderer { + + protected final StringBuilder html; + + public HTMLRenderer() { + this(new StringBuilder()); + } + + public HTMLRenderer(final StringBuilder html) { + this.html = html; + } + + @Override + public void code(final String code, @Nullable final String lang, final boolean escaped) { + if (lang == null) { + html.append("
    ");
    +			html.append(escaped ? code : htmlEscape(code, true));
    +			html.append("\n
    "); + } else { + html.append("
    ");
    +			html.append(escaped ? code : htmlEscape(code, true));
    +			html.append("\n
    "); + } + } + + @Override + public void blockquote(final String quote) { + // TODO Auto-generated method stub + + } + + @Override + public void html(final String html) { + // TODO Auto-generated method stub + + } + + @Override + public void heading(final String text, final int level, final String raw) { + html.append(""); + html.append(text); + html.append("\n"); + } + + @Override + public void hr() { + html.append("
    \n"); + } + + @Override + public void list(final String body, final boolean ordered) { + // TODO Auto-generated method stub + + } + + @Override + public void listitem(final String text) { + // TODO Auto-generated method stub + + } + + @Override + public void startParagraph() { + html.append("

    "); + } + + @Override + public void endParagraph() { + html.append("

    \n"); + } + + @Override + public void table(final String header, final String body) { + // TODO Auto-generated method stub + + } + + @Override + public void tablerow(final String content) { + // TODO Auto-generated method stub + + } + + @Override + public void tablecell(final String content, final String flags) { + // TODO Auto-generated method stub + + } + + @Override + public void startEm() { + html.append(""); + } + + @Override + public void endEm() { + html.append(""); + } + + @Override + public void startStrong() { + html.append(""); + } + + @Override + public void endStrong() { + html.append(""); + } + + @Override + public void codespan(final String text) { + html.append(""); + html.append(text); + html.append(""); + } + + @Override + public void br() { + // TODO Auto-generated method stub + + } + + @Override + public void del(final String text) { + // TODO Auto-generated method stub + + } + + @Override + public void link(final String href, final String title, final String text) { + // TODO Auto-generated method stub + + } + + @Override + public void image(final String href, final String title, final String text) { + // TODO Auto-generated method stub + + } + + @Override + public void text(final String text) { + html.append(text); + } + + @Override + public String toString() { + return html.toString(); + } +} diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Helpers.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Helpers.java index c6b1c15b2..5c9d48f5b 100644 --- a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Helpers.java +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Helpers.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,28 +11,23 @@ * Initial license: MIT * * Contributors: - * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.markdown.marked; - -public class Helpers { - - public static String escape(String html) { - return escape(html, false); - } - - public static String escape(String html, boolean encode) { - return html - .replaceAll(!encode ? "&(?!#?\\w+;)" : "&", "&") - .replaceAll("<", "<") - .replaceAll(">", ">") - .replaceAll("\"", """) - .replaceAll("'", "'"); - } - - public static boolean isEmpty(String s) { - return s == null || s.length() < 1; - } - -} + * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.markdown.marked; + +public class Helpers { + + public static String htmlEscape(final String html) { + return htmlEscape(html, false); + } + + public static String htmlEscape(final String html, final boolean encode) { + return html + .replaceAll(!encode ? "&(?!#?\\w+;)" : "&", "&") + .replace("<", "<") + .replace(">", ">") + .replace("\"", """) + .replace("'", "'"); + } +} diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/IRenderer.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/IRenderer.java index b499db8d1..820d08118 100644 --- a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/IRenderer.java +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/IRenderer.java @@ -13,55 +13,57 @@ * Contributors: * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.markdown.marked; - -public interface IRenderer { - - void code(String code, String lang, boolean escaped); - - void blockquote(String quote); - - void html(String html); - - void heading(String text, int level, String raw); - - void hr(); - - void list(String body, boolean ordered); - - void listitem(String text); - - void startParagraph(); - - void endParagraph(); - - void table(String header, String body); - - void tablerow(String content); - - void tablecell(String content, String flags); - - void startEm(); - - void endEm(); - - void startStrong(); - - void endStrong(); - - void codespan(String text); - - void br(); - - void del(String text); - - void link(String href, String title, String text); - - void image(String href, String title, String text); - - void text(String text); - - - -} + */ +package org.eclipse.tm4e.markdown.marked; + +import org.eclipse.jdt.annotation.Nullable; + +public interface IRenderer { + + void code(String code, @Nullable String lang, boolean escaped); + + void blockquote(String quote); + + void html(String html); + + void heading(String text, int level, String raw); + + void hr(); + + void list(String body, boolean ordered); + + void listitem(String text); + + void startParagraph(); + + void endParagraph(); + + void table(String header, String body); + + void tablerow(String content); + + void tablecell(String content, String flags); + + void startEm(); + + void endEm(); + + void startStrong(); + + void endStrong(); + + void codespan(String text); + + void br(); + + void del(String text); + + void link(String href, String title, String text); + + void image(String href, String title, String text); + + void text(String text); + + + +} diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/InlineLexer.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/InlineLexer.java index 2c07355c2..cedac1cee 100644 --- a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/InlineLexer.java +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/InlineLexer.java @@ -13,84 +13,87 @@ * Contributors: * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.markdown.marked; - -import static org.eclipse.tm4e.markdown.marked.Helpers.escape; -import static org.eclipse.tm4e.markdown.marked.Helpers.isEmpty; - -import java.util.regex.Matcher; - -public class InlineLexer { - - private Options options; - private InlineRules rules; - private final IRenderer renderer; - - public InlineLexer(Object links, Options options, IRenderer renderer) { - this.options = options != null ? options : Options.DEFAULTS; - // this.links = links; - this.rules = InlineRules.normal; - this.renderer = renderer != null ? renderer : new HTMLRenderer(); - // this.renderer = this.options.renderer || new Renderer; - // this.renderer.options = this.options; - - // if (!this.links) { - // throw new - // Error('Tokens array requires a `links` property.'); - // } - - if (this.options.isGfm()) { - if (this.options.isBreaks()) { - this.rules = InlineRules.breaks; - } else { - this.rules = InlineRules.gfm; - } - } else if (this.options.isPedantic()) { - this.rules = InlineRules.pedantic; - } - } - - public void output(String src) { - Matcher cap = null; - while (!isEmpty(src)) { - - // strong - if ((cap = this.rules.strong.exec(src)) != null) { - src = src.substring(cap.group(0).length()); - this.renderer.startStrong(); - this.output(!isEmpty(cap.group(2)) ? cap.group(2) : cap.group(1)); - this.renderer.endStrong(); - continue; - } - - // em - if ((cap = this.rules.em.exec(src)) != null) { - src = src.substring(cap.group(0).length()); - this.renderer.startEm(); - this.output(!isEmpty(cap.group(2)) ? cap.group(2) : cap.group(1)); - this.renderer.endEm(); - continue; - } - - // code - if ((cap = this.rules.code.exec(src)) != null) { - src = src.substring(cap.group(0).length()); - this.renderer.codespan(escape(cap.group(2), true)); - continue; - } - - // text - if ((cap = this.rules.text.exec(src)) != null) { - src = src.substring(cap.group(0).length()); - this.renderer.text(escape(this.smartypants(cap.group(0)))); - continue; - } - } - } - - private String smartypants(String text) { - return text; - } - -} + */ +package org.eclipse.tm4e.markdown.marked; + +import static org.eclipse.tm4e.markdown.marked.Helpers.htmlEscape; + +import com.google.common.base.Strings; +import java.util.regex.Matcher; + +import org.eclipse.jdt.annotation.Nullable; + +public class InlineLexer { + + private final Options options; + private final InlineRules rules; + private final IRenderer renderer; + + public InlineLexer(@Nullable final Object links, @Nullable final Options options, @Nullable final IRenderer renderer) { + this.options = options != null ? options : Options.DEFAULTS; + // this.links = links; + this.renderer = renderer != null ? renderer : new HTMLRenderer(); + // this.renderer = this.options.renderer || new Renderer; + // this.renderer.options = this.options; + + // if (!this.links) { + // throw new + // Error('Tokens array requires a `links` property.'); + // } + + if (this.options.isGfm()) { + if (this.options.isBreaks()) { + this.rules = InlineRules.breaks; + } else { + this.rules = InlineRules.gfm; + } + } else if (this.options.isPedantic()) { + this.rules = InlineRules.pedantic; + } else { + this.rules = InlineRules.normal; + } + } + + public void output(String src) { + Matcher cap = null; + while (!Strings.isNullOrEmpty(src)) { + + // strong + if ((cap = this.rules.strong.exec(src)) != null) { + src = src.substring(cap.group(0).length()); + this.renderer.startStrong(); + this.output(!Strings.isNullOrEmpty(cap.group(2)) ? cap.group(2) : cap.group(1)); + this.renderer.endStrong(); + continue; + } + + // em + if ((cap = this.rules.em.exec(src)) != null) { + src = src.substring(cap.group(0).length()); + this.renderer.startEm(); + this.output(!Strings.isNullOrEmpty(cap.group(2)) ? cap.group(2) : cap.group(1)); + this.renderer.endEm(); + continue; + } + + // code + if ((cap = this.rules.code.exec(src)) != null) { + src = src.substring(cap.group(0).length()); + this.renderer.codespan(htmlEscape(cap.group(2), true)); + continue; + } + + // text + if ((cap = this.rules.text.exec(src)) != null) { + src = src.substring(cap.group(0).length()); + this.renderer.text(htmlEscape(this.smartypants(cap.group(0)))); + continue; + } + } + } + + private String smartypants(final String text) { + return text; + } + +} diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/InlineRules.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/InlineRules.java index 6cb328c0c..b9b2e1ea9 100644 --- a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/InlineRules.java +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/InlineRules.java @@ -13,98 +13,98 @@ * Contributors: * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.markdown.marked; - -public class InlineRules { - - private static final String INLINE_INSIDE = "(?:\\[[^\\]]*\\]|[^\\[\\]]|\\](?=[^\\[]*\\]))*"; - private static final String INLINE_HREF = "\\s*?(?:\\s+['\"]([\\s\\S]*?)['\"])?\\s*"; - - public static final InlineRules normal = normal(); - - public static final InlineRules pedantic = pedantic(); - - public static final InlineRules gfm = gfm(); - - public static final InlineRules breaks = breaks(); - - public final RegExp escape; - public final RegExp autolink; - public final RegExp url; - public final RegExp tag; - public final RegExp link; - public final RegExp reflink; - public final RegExp nolink; - public final RegExp strong; - public final RegExp em; - public final RegExp code; - public final RegExp br; - public final RegExp del; - public final RegExp text; - - public InlineRules(RegExp escape, RegExp autolink, RegExp url, RegExp tag, RegExp link, RegExp reflink, - RegExp nolink, RegExp strong, RegExp em, RegExp code, RegExp br, RegExp del, RegExp text) { - this.escape = escape; - this.autolink = autolink; - this.url = url; - this.tag = tag; - this.link = link; - this.reflink = reflink; - this.nolink = nolink; - this.strong = strong; - this.em = em; - this.code = code; - this.br = br; - this.del = del; - this.text = text; - } - - private static InlineRules inline() { - RegExp escape = new RegExp("^\\\\([\\\\`*{}\\[\\]()#+\\-.!_>])"); - RegExp autolink = new RegExp("^<([^ >]+(@|:\\/)[^ >]+)>"); - RegExp url = RegExp.noop(); - RegExp tag = new RegExp("^|^<\\/?\\w+(?:\"[^\"]*\"|'[^']*'|[^'\">])*?>"); - RegExp link = new RegExp("^!?\\[(inside)\\]\\(href\\)"); - RegExp reflink = new RegExp("^!?\\[(inside)\\]\\s*\\[([^\\]]*)\\]"); - RegExp nolink = new RegExp("^!?\\[((?:\\[[^\\]]*\\]|[^\\[\\]])*)\\]"); - RegExp strong = new RegExp("^__([\\s\\S]+?)__(?!_)|^\\*\\*([\\s\\S]+?)\\*\\*(?!\\*)"); - RegExp em = new RegExp("^\\b_((?:[^_]|__)+?)_\\b|^\\*((?:\\*\\*|[\\s\\S])+?)\\*(?!\\*)"); - RegExp code = new RegExp("^(`+)\\s*([\\s\\S]*?[^`])\\s*\\1(?!`)"); - RegExp br = new RegExp("^ {2,}\\n(?!\\s*$)"); - RegExp del = RegExp.noop(); - RegExp text = new RegExp("^[\\s\\S]+?(?=[\\\\?(?:\\s+['\"]([\\s\\S]*?)['\"])?\\s*"; + + public static final InlineRules normal = normal(); + + public static final InlineRules pedantic = pedantic(); + + public static final InlineRules gfm = gfm(); + + public static final InlineRules breaks = breaks(); + + public final RegExp escape; + public final RegExp autolink; + public final RegExp url; + public final RegExp tag; + public final RegExp link; + public final RegExp reflink; + public final RegExp nolink; + public final RegExp strong; + public final RegExp em; + public final RegExp code; + public final RegExp br; + public final RegExp del; + public final RegExp text; + + public InlineRules(final RegExp escape, final RegExp autolink, final RegExp url, final RegExp tag, final RegExp link, final RegExp reflink, + final RegExp nolink, final RegExp strong, final RegExp em, final RegExp code, final RegExp br, final RegExp del, final RegExp text) { + this.escape = escape; + this.autolink = autolink; + this.url = url; + this.tag = tag; + this.link = link; + this.reflink = reflink; + this.nolink = nolink; + this.strong = strong; + this.em = em; + this.code = code; + this.br = br; + this.del = del; + this.text = text; + } + + private static InlineRules inline() { + final RegExp escape = new RegExp("^\\\\([\\\\`*{}\\[\\]()#+\\-.!_>])"); + final RegExp autolink = new RegExp("^<([^ >]+(@|:\\/)[^ >]+)>"); + final RegExp url = RegExp.noop(); + final RegExp tag = new RegExp("^|^<\\/?\\w+(?:\"[^\"]*\"|'[^']*'|[^'\">])*?>"); + final RegExp link = new RegExp("^!?\\[(inside)\\]\\(href\\)"); + final RegExp reflink = new RegExp("^!?\\[(inside)\\]\\s*\\[([^\\]]*)\\]"); + final RegExp nolink = new RegExp("^!?\\[((?:\\[[^\\]]*\\]|[^\\[\\]])*)\\]"); + final RegExp strong = new RegExp("^__([\\s\\S]+?)__(?!_)|^\\*\\*([\\s\\S]+?)\\*\\*(?!\\*)"); + final RegExp em = new RegExp("^\\b_((?:[^_]|__)+?)_\\b|^\\*((?:\\*\\*|[\\s\\S])+?)\\*(?!\\*)"); + final RegExp code = new RegExp("^(`+)\\s*([\\s\\S]*?[^`])\\s*\\1(?!`)"); + final RegExp br = new RegExp("^ {2,}\\n(?!\\s*$)"); + final RegExp del = RegExp.noop(); + final RegExp text = new RegExp("^[\\s\\S]+?(?=[\\\\ - translation and adaptation to Java - */ -package org.eclipse.tm4e.markdown.marked; - -import static org.eclipse.tm4e.markdown.marked.Helpers.isEmpty; - -import java.util.regex.Matcher; - -public class Lexer { - - private BlockRules rules; - private final Tokens tokens; - private final Options options; - - public Lexer(Options options) { - this.tokens = new Tokens(); - this.options = options != null ? options : Options.DEFAULTS; - this.rules = BlockRules.normal; - - if (this.options.isGfm()) { - if (this.options.isTables()) { - this.rules = BlockRules.tables; - } else { - this.rules = BlockRules.gfm; - } - } - } - - public static Tokens lex(String src, Options options) { - Lexer lexer = new Lexer(options); - return lexer.lex(src); - } - - private Tokens lex(String src) { - src = src.replaceAll("\r\n|\r", "\n").replaceAll("\t", " ").replaceAll("\u00a0", " ").replaceAll("\u2424", - "\n"); - return this.token(src, true); - } - - private Tokens token(String src, boolean top) { - return token(src, top, null); - } - - private Tokens token(String src, boolean top, Object bq) { - src = src.replaceAll("^ +$", ""); - Matcher cap; - while (!isEmpty(src)) { - - // newline - if ((cap = this.rules.newline.exec(src)) != null) { - src = src.substring(cap.group(0).length()); - if (cap.group(0).length() > 1) { - this.tokens.add(new Token(TokenType.space)); - } - } - - // code - // if ((cap = this.rules.code.exec(src)) != null) { - // src = src.substring(cap.group(0).length()); - // cap = cap.group(0).matches("^ {4}", ""); - // String text = !this.options.pedantic - // ? cap.replace(/\n+$/, '') - // : cap; - // this.tokens.add(new Token(TokenType.type)); - // continue; - // } - - // fences (gfm) - if ((cap = this.rules.fences.exec(src)) != null) { - src = src.substring(cap.group(0).length()); - String lang = cap.group(2); - String text = !isEmpty(cap.group(3)) ? cap.group(3) : ""; - this.tokens.add(new Token(TokenType.code, lang, text)); - continue; - } - - // heading - if ((cap = this.rules.heading.exec(src)) != null) { - src = src.substring(cap.group(0).length()); - String text = cap.group(2); - int depth = cap.group(1).length(); - this.tokens.add(new Token(TokenType.heading, text, depth)); - continue; - } - - // table no leading pipe (gfm) - // TODO - - // lheading - if ((cap = this.rules.lheading.exec(src)) != null) { - src = src.substring(cap.group(0).length()); - String text = cap.group(1); - int depth = cap.group(2).equals("=") ? 1 : 2; - this.tokens.add(new Token(TokenType.heading, text, depth)); - continue; - } - - // hr - if ((cap = this.rules.hr.exec(src)) != null) { - src = src.substring(cap.group(0).length()); - this.tokens.add(new Token(TokenType.hr)); - continue; - } - - // top-level paragraph - if (top && ((cap = this.rules.paragraph.exec(src)) != null)) { - src = src.substring(cap.group(0).length()); - String text = cap.group(1).charAt(cap.group(1).length() - 1) == '\n' ? cap.group(1) : cap.group(1); - this.tokens.add(new Token(TokenType.paragraph, text)); - continue; - } - } - return this.tokens; - } - -} + */ +package org.eclipse.tm4e.markdown.marked; + +import java.util.regex.Matcher; + +import com.google.common.base.Strings; +import org.eclipse.jdt.annotation.Nullable; + +public class Lexer { + + private final BlockRules rules; + private final Tokens tokens; + private final Options options; + + public Lexer(@Nullable final Options options) { + this.tokens = new Tokens(); + this.options = options != null ? options : Options.DEFAULTS; + + if (this.options.isGfm()) { + if (this.options.isTables()) { + this.rules = BlockRules.tables; + } else { + this.rules = BlockRules.gfm; + } + } else { + this.rules = BlockRules.normal; + } + } + + public static Tokens lex(final String src, @Nullable final Options options) { + final Lexer lexer = new Lexer(options); + return lexer.lex(src); + } + + private Tokens lex(String src) { + src = src.replaceAll("\r\n|\r", "\n").replaceAll("\t", " ").replaceAll("\u00a0", " ").replaceAll("\u2424", + "\n"); + return this.token(src, true); + } + + private Tokens token(final String src, final boolean top) { + return token(src, top, null); + } + + private Tokens token(String src, final boolean top, @Nullable final Object bq) { + src = src.replaceAll("^ +$", ""); + Matcher cap; + while (!Strings.isNullOrEmpty(src)) { + + // newline + if ((cap = this.rules.newline.exec(src)) != null) { + src = src.substring(cap.group(0).length()); + if (cap.group(0).length() > 1) { + this.tokens.add(new Token(TokenType.space)); + } + } + + // code + // if ((cap = this.rules.code.exec(src)) != null) { + // src = src.substring(cap.group(0).length()); + // cap = cap.group(0).matches("^ {4}", ""); + // String text = !this.options.pedantic + // ? cap.replace(/\n+$/, '') + // : cap; + // this.tokens.add(new Token(TokenType.type)); + // continue; + // } + + // fences (gfm) + if ((cap = this.rules.fences.exec(src)) != null) { + src = src.substring(cap.group(0).length()); + final String lang = cap.group(2); + final String text = !Strings.isNullOrEmpty(cap.group(3)) ? cap.group(3) : ""; + this.tokens.add(new Token(TokenType.code, lang, text)); + continue; + } + + // heading + if ((cap = this.rules.heading.exec(src)) != null) { + src = src.substring(cap.group(0).length()); + final String text = cap.group(2); + final int depth = cap.group(1).length(); + this.tokens.add(new Token(TokenType.heading, text, depth)); + continue; + } + + // table no leading pipe (gfm) + // TODO + + // lheading + if ((cap = this.rules.lheading.exec(src)) != null) { + src = src.substring(cap.group(0).length()); + final String text = cap.group(1); + final int depth = cap.group(2).equals("=") ? 1 : 2; + this.tokens.add(new Token(TokenType.heading, text, depth)); + continue; + } + + // hr + if ((cap = this.rules.hr.exec(src)) != null) { + src = src.substring(cap.group(0).length()); + this.tokens.add(new Token(TokenType.hr)); + continue; + } + + // top-level paragraph + if (top && ((cap = this.rules.paragraph.exec(src)) != null)) { + src = src.substring(cap.group(0).length()); + final String text = cap.group(1).charAt(cap.group(1).length() - 1) == '\n' ? cap.group(1) : cap.group(1); + this.tokens.add(new Token(TokenType.paragraph, text)); + continue; + } + } + return this.tokens; + } + +} diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Marked.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Marked.java index ee2267bfe..283d1a020 100644 --- a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Marked.java +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Marked.java @@ -13,25 +13,26 @@ * Contributors: * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.markdown.marked; - -public class Marked { - - public static IRenderer parse(String src) { - return parse(src, (Options) null); - } - - public static IRenderer parse(String src, IRenderer renderer) { - return parse(src, null, renderer); - } - - public static IRenderer parse(String src, Options opt) { - return parse(src, opt, null); - } - - public static IRenderer parse(String src, Options opt, IRenderer renderer) { - - return Parser.parse(Lexer.lex(src, opt), opt, renderer); - } -} + */ +package org.eclipse.tm4e.markdown.marked; + +import org.eclipse.jdt.annotation.Nullable; + +public class Marked { + + public static IRenderer parse(final String src) { + return parse(src, (Options) null); + } + + public static IRenderer parse(final String src, final IRenderer renderer) { + return parse(src, null, renderer); + } + + public static IRenderer parse(final String src, @Nullable final Options opt) { + return parse(src, opt, null); + } + + public static IRenderer parse(final String src, @Nullable final Options opt, @Nullable final IRenderer renderer) { + return Parser.parse(Lexer.lex(src, opt), opt, renderer); + } +} diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Options.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Options.java index bf86ef868..87146b38d 100644 --- a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Options.java +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Options.java @@ -13,52 +13,52 @@ * Contributors: * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.markdown.marked; - -public class Options { - - public static final Options DEFAULTS = new Options(); - - private boolean gfm; - private boolean breaks; - private boolean pedantic; - private boolean tables; - - public Options() { - this.gfm = true; - } - - public boolean isGfm() { - return gfm; - } - - public void setGfm(boolean gfm) { - this.gfm = gfm; - } - - public boolean isBreaks() { - return breaks; - } - - public void setBreaks(boolean breaks) { - this.breaks = breaks; - } - - public boolean isPedantic() { - return pedantic; - } - - public void setPedantic(boolean pedantic) { - this.pedantic = pedantic; - } - - public boolean isTables() { - return tables; - } - - public void setTables(boolean tables) { - this.tables = tables; - } - -} + */ +package org.eclipse.tm4e.markdown.marked; + +public class Options { + + public static final Options DEFAULTS = new Options(); + + private boolean gfm; + private boolean breaks; + private boolean pedantic; + private boolean tables; + + public Options() { + this.gfm = true; + } + + public boolean isGfm() { + return gfm; + } + + public void setGfm(final boolean gfm) { + this.gfm = gfm; + } + + public boolean isBreaks() { + return breaks; + } + + public void setBreaks(final boolean breaks) { + this.breaks = breaks; + } + + public boolean isPedantic() { + return pedantic; + } + + public void setPedantic(final boolean pedantic) { + this.pedantic = pedantic; + } + + public boolean isTables() { + return tables; + } + + public void setTables(final boolean tables) { + this.tables = tables; + } + +} diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Parser.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Parser.java index 6b4b81ea2..1c9012e46 100644 --- a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Parser.java +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Parser.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,76 +11,80 @@ * Initial license: MIT * * Contributors: - * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.markdown.marked; - -public class Parser { - - private Tokens tokens; - private Token token; - private Options options; - private InlineLexer inline; - private IRenderer renderer; - - public Parser(Options options, IRenderer renderer) { - this.tokens = new Tokens(); - this.token = null; - this.options = options != null ? options : Options.DEFAULTS; - this.renderer = renderer != null ? renderer : new HTMLRenderer(); - } - - public static IRenderer parse(Tokens src, Options options, IRenderer renderer) { - Parser parser = new Parser(options, renderer); - return parser.parse(src); - } - - private IRenderer parse(Tokens src) { - this.inline = new InlineLexer(src.links, this.options, this.renderer); - this.tokens = src.reverse(); - - // var out = ''; - while (this.next()) { - // out += this.tok(); - this.tok(); - } - - return renderer; - } - - /** - * Next Token - */ - private boolean next() { - return ((this.token = this.tokens.pop()) != null); - } - - /** - * Parse Current Token - */ - private void tok() { - switch (this.token.type) { - case space: - break; - case hr: - this.renderer.hr(); - break; - case heading: - // this.renderer.heading(this.inline.output(this.token.text), - // this.token.depth, this.token.text); - this.renderer.heading(this.token.text, this.token.depth, this.token.text); - break; - case code: - this.renderer.code(this.token.text, this.token.lang, this.token.escaped); - break; - case paragraph: - this.renderer.startParagraph(); - this.inline.output(this.token.text); - this.renderer.endParagraph(); - break; - } - - } - -} + * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.markdown.marked; + +import org.eclipse.jdt.annotation.Nullable; + +import com.google.common.base.Strings; + +public class Parser { + + private final Options options; + private final IRenderer renderer; + + @Nullable + private Token token; + + public Parser(@Nullable final Options options, @Nullable final IRenderer renderer) { + this.options = options != null ? options : Options.DEFAULTS; + this.renderer = renderer != null ? renderer : new HTMLRenderer(); + } + + public static IRenderer parse(final Tokens src, @Nullable final Options options, + @Nullable final IRenderer renderer) { + final Parser parser = new Parser(options, renderer); + return parser.parse(src); + } + + private IRenderer parse(final Tokens src) { + final var inline = new InlineLexer(src.links, this.options, this.renderer); + final var tokens = src.reverse(); + + // var out = ''; + while (this.next(tokens)) { + // out += this.tok(); + this.tok(inline); + } + + return renderer; + } + + /** + * Next Token + */ + private boolean next(Tokens tokens) { + return ((this.token = tokens.pop()) != null); + } + + /** + * Parse Current Token + */ + private void tok(InlineLexer inline) { + final var token = this.token; + if (token == null) + return; + + switch (token.type) { + case space: + break; + case hr: + this.renderer.hr(); + break; + case heading: + // this.renderer.heading(this.inline.output(token.text), token.depth, token.text); + this.renderer.heading(Strings.nullToEmpty(token.text), token.depth, Strings.nullToEmpty(token.text)); + break; + case code: + this.renderer.code(Strings.nullToEmpty(token.text), token.lang, token.escaped); + break; + case paragraph: + this.renderer.startParagraph(); + inline.output(Strings.nullToEmpty(token.text)); + this.renderer.endParagraph(); + break; + } + } +} diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/RegExp.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/RegExp.java index ff0e17bf9..cb15fb366 100644 --- a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/RegExp.java +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/RegExp.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,63 +11,82 @@ * Initial license: MIT * * Contributors: - * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.markdown.marked; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class RegExp { - - protected String source; - private Pattern pattern; - - public RegExp(String source) { - this.source = source; - } - - public Matcher exec(String s) { - if (source == null) { - return null; - } - if (pattern == null) { - pattern = Pattern.compile(source); - } - Matcher matcher = pattern.matcher(s); - if (matcher.find()) { - return matcher; - } - return null; - } - - public RegExp replace(String name, RegExp val) { - return replace(name, val.source); - } - - public RegExp replace(String name, String val) { - if (name == null) - return new RegExp(this.source); - val = val.replaceAll("(^|[^\\[])\\^", "$1"); - this.source = this.source.replaceFirst(name, Matcher.quoteReplacement(val)); - return this; - } - - public RegExp replaceAll(String name, RegExp val) { - return replaceAll(name, val.source); - } - - public RegExp replaceAll(String name, String val) { - if (name == null) - return new RegExp(this.source); - val = val.replaceAll("(^|[^\\[])\\^", "$1"); - this.source = this.source.replaceAll(name, Matcher.quoteReplacement(val)); - return this; - } - - public static final RegExp noop() { - return new RegExp(null); - } - -} + * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.markdown.marked; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.jdt.annotation.Nullable; + +public class RegExp { + + @Nullable + protected String source; + + @Nullable + private Pattern pattern; + + public RegExp(@Nullable final String source) { + this.source = source; + } + + @Nullable + public Matcher exec(final String s) { + if (source == null) { + return null; + } + + if (pattern == null) { + pattern = Pattern.compile(source); + } + + assert pattern != null; + final Matcher matcher = pattern.matcher(s); + if (matcher.find()) { + return matcher; + } + return null; + } + + public RegExp replace(final String name, final RegExp val) { + return replace(name, val.source); + } + + public RegExp replace(@Nullable final String name, @Nullable String val) { + final var source = this.source; + + if (name == null) + return new RegExp(source); + + if (source != null && val != null) { + val = val.replaceAll("(^|[^\\[])\\^", "$1"); + this.source = source.replaceFirst(name, Matcher.quoteReplacement(val)); + } + return this; + } + + public RegExp replaceAll(final String name, final RegExp val) { + return replaceAll(name, val.source); + } + + public RegExp replaceAll(@Nullable final String name, @Nullable String val) { + final var source = this.source; + + if (name == null) + return new RegExp(source); + + if (source != null && val != null) { + val = val.replaceAll("(^|[^\\[])\\^", "$1"); + this.source = source.replaceAll(name, Matcher.quoteReplacement(val)); + } + return this; + } + + public static final RegExp noop() { + return new RegExp(null); + } + +} diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Token.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Token.java index 143f0f07a..8dad861f9 100644 --- a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Token.java +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Token.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -11,40 +11,47 @@ * Initial license: MIT * * Contributors: - * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license - * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.markdown.marked; - -public class Token { - - public final TokenType type; - public final String text; - public final int depth; - public final String lang; - public final boolean escaped; - - public Token(TokenType type) { - this(type, null); - } - - public Token(TokenType type, String text) { - this(type, text, -1); - } - - public Token(TokenType type, String text, int depth) { - this(type, text, depth, null, false); - } - - public Token(TokenType type, String lang, String text) { - this(type, text, -1, lang, false); - } - - private Token(TokenType type, String text, int depth, String lang, boolean escaped) { - this.type = type; - this.text = text; - this.depth = depth; - this.lang = lang; - this.escaped = escaped; - } -} + * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license + * - Angelo Zerr - translation and adaptation to Java + */ +package org.eclipse.tm4e.markdown.marked; + +import org.eclipse.jdt.annotation.Nullable; + +public class Token { + + public final TokenType type; + + @Nullable + public final String text; + public final int depth; + + @Nullable + public final String lang; + public final boolean escaped; + + public Token(final TokenType type) { + this(type, null); + } + + public Token(final TokenType type, @Nullable final String text) { + this(type, text, -1); + } + + public Token(final TokenType type, @Nullable final String text, final int depth) { + this(type, text, depth, null, false); + } + + public Token(final TokenType type, final String lang, final String text) { + this(type, text, -1, lang, false); + } + + private Token(final TokenType type, @Nullable final String text, final int depth, @Nullable final String lang, + final boolean escaped) { + this.type = type; + this.text = text; + this.depth = depth; + this.lang = lang; + this.escaped = escaped; + } +} diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/TokenType.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/TokenType.java index d15dfd1e7..90b14e2a7 100644 --- a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/TokenType.java +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/TokenType.java @@ -13,10 +13,10 @@ * Contributors: * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.markdown.marked; - -public enum TokenType { - - space, hr, heading, code, table, blockquote_start, blockquote_end, list_start, list_end, list_item_start, list_item_end, loose_item_start, html, paragraph, text; -} + */ +package org.eclipse.tm4e.markdown.marked; + +public enum TokenType { + + space, hr, heading, code, table, blockquote_start, blockquote_end, list_start, list_end, list_item_start, list_item_end, loose_item_start, html, paragraph, text; +} diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Tokens.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Tokens.java index 597f0c3db..c416d7363 100644 --- a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Tokens.java +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/Tokens.java @@ -13,26 +13,32 @@ * Contributors: * - Christopher Jeffrey and others: Initial code, written in JavaScript, licensed under MIT license * - Angelo Zerr - translation and adaptation to Java - */ -package org.eclipse.tm4e.markdown.marked; - -import java.util.ArrayList; -import java.util.Collections; - -public class Tokens extends ArrayList { - - public Object links; - - public Tokens reverse() { - Collections.reverse(this); - return this; - } - - public Token pop() { - if (super.isEmpty()) { - return null; - } - return super.remove(super.size() - 1); - } - -} + */ +package org.eclipse.tm4e.markdown.marked; + +import java.util.ArrayList; +import java.util.Collections; + +import org.eclipse.jdt.annotation.Nullable; + +public class Tokens extends ArrayList { + + private static final long serialVersionUID = 1L; + + @Nullable + public Object links; + + public Tokens reverse() { + Collections.reverse(this); + return this; + } + + @Nullable + public Token pop() { + if (super.isEmpty()) { + return null; + } + return super.remove(super.size() - 1); + } + +} diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/package-info.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/package-info.java new file mode 100644 index 000000000..1d8f1dd21 --- /dev/null +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/marked/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.markdown.marked; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/package-info.java b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/package-info.java new file mode 100644 index 000000000..8a091b0de --- /dev/null +++ b/org.eclipse.tm4e.markdown/src/main/java/org/eclipse/tm4e/markdown/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.markdown; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.registry/.classpath b/org.eclipse.tm4e.registry/.classpath index b931e34ba..71f21812a 100644 --- a/org.eclipse.tm4e.registry/.classpath +++ b/org.eclipse.tm4e.registry/.classpath @@ -1,7 +1,27 @@ - + + + + + - - + + + + + + + + + + + + + + + + + + diff --git a/org.eclipse.tm4e.registry/.gitignore b/org.eclipse.tm4e.registry/.gitignore deleted file mode 100644 index ae3c17260..000000000 --- a/org.eclipse.tm4e.registry/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/org.eclipse.tm4e.registry/.project b/org.eclipse.tm4e.registry/.project index a34f25782..09f9e611f 100644 --- a/org.eclipse.tm4e.registry/.project +++ b/org.eclipse.tm4e.registry/.project @@ -20,9 +20,15 @@ + + org.eclipse.m2e.core.maven2Builder + + + - org.eclipse.pde.PluginNature org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.pde.PluginNature diff --git a/org.eclipse.tm4e.registry/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.tm4e.registry/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..6b99f88fc --- /dev/null +++ b/org.eclipse.tm4e.registry/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,518 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.APILeak=warning +org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning +org.eclipse.jdt.core.compiler.problem.fallthroughCase=info +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=info +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=info +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=enabled +org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=11 +org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false +org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false +org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter=0 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type=49 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assertion_message=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0 +org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_record_components=16 +org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_type_annotations=0 +org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0 +org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch=0 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_constructor=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false +org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true +org.eclipse.jdt.core.formatter.comment.format_block_comments=false +org.eclipse.jdt.core.formatter.comment.format_header=true +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.indent_tag_description=false +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=120 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_not_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false +org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.text_block_indentation=0 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false +org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true +org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true +org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true +org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true +org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/org.eclipse.tm4e.registry/META-INF/MANIFEST.MF b/org.eclipse.tm4e.registry/META-INF/MANIFEST.MF index 738661f85..c72e792e1 100644 --- a/org.eclipse.tm4e.registry/META-INF/MANIFEST.MF +++ b/org.eclipse.tm4e.registry/META-INF/MANIFEST.MF @@ -3,9 +3,9 @@ Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-SymbolicName: org.eclipse.tm4e.registry;singleton:=true -Bundle-Version: 0.5.0.qualifier +Bundle-Version: 0.5.1.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-11 -Require-Bundle: org.eclipse.tm4e.core, +Require-Bundle: org.eclipse.tm4e.core;bundle-version="0.4.4", org.eclipse.core.runtime, com.google.gson, org.eclipse.equinox.preferences diff --git a/org.eclipse.tm4e.registry/build.properties b/org.eclipse.tm4e.registry/build.properties index ebceaad62..d51a4353e 100644 --- a/org.eclipse.tm4e.registry/build.properties +++ b/org.eclipse.tm4e.registry/build.properties @@ -1,5 +1,5 @@ -source.. = src/main/java -output.. = bin/ +source.. = src/main/java/,\ + src/main/resources/ bin.includes = META-INF/,\ schema/,\ plugin.xml,\ @@ -7,3 +7,9 @@ bin.includes = META-INF/,\ .,\ .options,\ about.html + +# https://codeiseasy.wordpress.com/2013/03/08/tycho-and-jdt-null-analysis/ +# JDT Null Analysis for Eclipse +additional.bundles = org.eclipse.jdt.annotation +# JDT Null Analysis types for Tycho +jars.extra.classpath = platform:/plugin/org.eclipse.jdt.annotation diff --git a/org.eclipse.tm4e.registry/pom.xml b/org.eclipse.tm4e.registry/pom.xml index b06147cff..83044e50d 100644 --- a/org.eclipse.tm4e.registry/pom.xml +++ b/org.eclipse.tm4e.registry/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.eclipse.tm4e.registry eclipse-plugin - 0.5.0-SNAPSHOT + 0.5.1-SNAPSHOT org.eclipse org.eclipse.tm4e diff --git a/org.eclipse.tm4e.registry/schema/grammars.exsd b/org.eclipse.tm4e.registry/schema/grammars.exsd index ee8c8c712..fec6c3d5d 100644 --- a/org.eclipse.tm4e.registry/schema/grammars.exsd +++ b/org.eclipse.tm4e.registry/schema/grammars.exsd @@ -6,7 +6,7 @@ - Extension point to register TextMate grammars *.tmLanguage, *.json (VSCode format). + Extension point to register TextMate grammars *.tmLanguage, *.json (VSCode format), *.YAML-tmLanguage, *.yaml, *.yml. diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/GrammarDefinition.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/GrammarDefinition.java index 9685cb0d3..f869fed78 100644 --- a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/GrammarDefinition.java +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/GrammarDefinition.java @@ -1,61 +1,63 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.registry; - -import org.eclipse.core.runtime.IConfigurationElement; - -/** - * Grammar definition defined by the "org.eclipse.tm4e.registry.grammars" - * extension point. Here a sample to register TypeScript TextMate grammar. - * - *
    - * 
    -      
    -      
    -   
    - * 
    - * - */ -public class GrammarDefinition extends TMResource implements IGrammarDefinition { - - private String scopeName; - - /** - * Constructor for user preferences (loaded from Json with Gson). - */ - public GrammarDefinition() { - super(); - } - - /** - * Constructor for extension point. - * - * @param element - */ - public GrammarDefinition(String scopeName, String path) { - super(path); - this.scopeName = scopeName; - } - - public GrammarDefinition(IConfigurationElement ce) { - super(ce); - this.scopeName = ce.getAttribute(XMLConstants.SCOPE_NAME_ATTR); - } - - @Override - public String getScopeName() { - return scopeName; - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.registry; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.jdt.annotation.Nullable; + +/** + * Grammar definition defined by the "org.eclipse.tm4e.registry.grammars" + * extension point. Here a sample to register TypeScript TextMate grammar. + * + *
    + * 
    +      
    +      
    +   
    + * 
    + * + */ +public class GrammarDefinition extends TMResource implements IGrammarDefinition { + + @Nullable + private String scopeName; + + /** + * Constructor for user preferences (loaded from Json with Gson). + */ + public GrammarDefinition() { + } + + /** + * Constructor for extension point. + * + * @param scopeName + */ + public GrammarDefinition(final String scopeName, final String path) { + super(path); + this.scopeName = scopeName; + } + + public GrammarDefinition(final IConfigurationElement ce) { + super(ce); + this.scopeName = ce.getAttribute(XMLConstants.SCOPE_NAME_ATTR); + } + + @Override + public String getScopeName() { + assert scopeName != null; + return scopeName; + } +} diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/IGrammarDefinition.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/IGrammarDefinition.java index d4cfc1470..b53be1a0b 100644 --- a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/IGrammarDefinition.java +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/IGrammarDefinition.java @@ -1,26 +1,26 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.registry; - -/** - * TextMate grammar definition API. - * - */ -public interface IGrammarDefinition extends ITMResource { - - /** - * Returns the scope name of the TextMate grammar. - * - * @return the scope name of the TextMate grammar. - */ - String getScopeName(); -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.registry; + +/** + * TextMate grammar definition API. + * + */ +public interface IGrammarDefinition extends ITMResource { + + /** + * Returns the scope name of the TextMate grammar. + * + * @return the scope name of the TextMate grammar. + */ + String getScopeName(); +} diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/IGrammarRegistryManager.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/IGrammarRegistryManager.java index 79c8662f3..3a91a372c 100644 --- a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/IGrammarRegistryManager.java +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/IGrammarRegistryManager.java @@ -1,100 +1,100 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.registry; - -import java.util.Collection; -import java.util.List; - -import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.tm4e.core.grammar.IGrammar; -import org.osgi.service.prefs.BackingStoreException; - -/** - * - * TextMate Grammar registry manager API. - * - */ -public interface IGrammarRegistryManager { - - // --------------- TextMate grammar definitions methods - - /** - * Returns the list of registered TextMate grammar definitions. - * - * @return the list of registered TextMate grammar definitions. - */ - IGrammarDefinition[] getDefinitions(); - - /** - * Add grammar definition to the registry. - * - * NOTE: you must call save() method if you wish to save in the preferences. - * - * @param definition - */ - void registerGrammarDefinition(IGrammarDefinition definition); - - /** - * Remove grammar definition from the registry. - * - * NOTE: you must call save() method if you wish to save in the preferences. - * - * @param definition - */ - void unregisterGrammarDefinition(IGrammarDefinition definition); - - /** - * Save the grammar definitions. - * @throws BackingStoreException - */ - void save() throws BackingStoreException; - - // --------------- TextMate grammar queries methods. - - /** - * @param contentTypes the content types to lookup for grammar association. - * @return the first {@link IGrammar} that applies to given content-types, or - * null if no content-type has a grammar associated. Grammars associated - * with parent content-types will be returned if applicable. - */ - IGrammar getGrammarFor(IContentType[] contentTypes); - - /** - * Returns the {@link IGrammar} for the given scope name and null otherwise. - * - * @param contentTypes - * the content type. - * @return the {@link IGrammar} for the given scope name and null otherwise. - */ - IGrammar getGrammarForScope(String scopeName); - - /** - * Returns the {@link IGrammar} for the given file type and null otherwise. - * - * @param contentTypes - * the content type. - * @return the {@link IGrammar} for the file type name and null otherwise. - */ - IGrammar getGrammarForFileType(String fileType); - - /** - * Returns the list of content types bound with the given scope name and - * null otherwise. - * - * @param scopeName - * @return the list of content types bound with the given scope name and - * null otherwise. - */ - List getContentTypesForScope(String scopeName); - - Collection getInjections(String scopeName); -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.registry; + +import java.util.Collection; +import java.util.List; + +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.grammar.IGrammar; +import org.osgi.service.prefs.BackingStoreException; + +/** + * + * TextMate Grammar registry manager API. + * + */ +public interface IGrammarRegistryManager { + + // --------------- TextMate grammar definitions methods + + /** + * Returns the list of registered TextMate grammar definitions. + * + * @return the list of registered TextMate grammar definitions. + */ + IGrammarDefinition[] getDefinitions(); + + /** + * Add grammar definition to the registry. + * + * NOTE: you must call save() method if you wish to save in the preferences. + */ + void registerGrammarDefinition(IGrammarDefinition definition); + + /** + * Remove grammar definition from the registry. + * + * NOTE: you must call save() method if you wish to save in the preferences. + */ + void unregisterGrammarDefinition(IGrammarDefinition definition); + + /** + * Save the grammar definitions. + * @throws BackingStoreException + */ + void save() throws BackingStoreException; + + // --------------- TextMate grammar queries methods. + + /** + * @param contentTypes the content types to lookup for grammar association. + * @return the first {@link IGrammar} that applies to given content-types, or + * null if no content-type has a grammar associated. Grammars associated + * with parent content-types will be returned if applicable. + */ + @Nullable + IGrammar getGrammarFor(IContentType @Nullable[] contentTypes); + + /** + * Returns the {@link IGrammar} for the given scope name and null otherwise. + * + * @return the {@link IGrammar} for the given scope name and null otherwise. + */ + @Nullable + IGrammar getGrammarForScope(String scopeName); + + /** + * Returns the {@link IGrammar} for the given file type and null otherwise. + * + * @return the {@link IGrammar} for the file type name and null otherwise. + */ + @Nullable + IGrammar getGrammarForFileType(String fileType); + + /** + * Returns the list of content types bound with the given scope name and null otherwise. + * + * @return the list of content types bound with the given scope name and null otherwise. + */ + @Nullable + List getContentTypesForScope(String scopeName); + + /** + * Returns list of scope names to inject for the given scopeName and null otherwise. + * + * @return list of scope names to inject for the given scopeName and null otherwise. + */ + @Nullable + Collection getInjections(String scopeName); +} diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/ITMDefinition.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/ITMDefinition.java index c9dda95b4..79d35ca87 100644 --- a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/ITMDefinition.java +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/ITMDefinition.java @@ -1,27 +1,30 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.registry; - -/** - * TextMate definition API. - * - */ -public interface ITMDefinition { - - /** - * Returns the plugin id which has registered the TextMate resource. - * - * @return the plugin id which has registered the TextMate resource. - */ - String getPluginId(); - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.registry; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * TextMate definition API. + * + */ +public interface ITMDefinition { + + /** + * Returns the plugin id which has registered the TextMate resource. + * + * @return the plugin id which has registered the TextMate resource. + */ + @Nullable + String getPluginId(); + +} diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/ITMResource.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/ITMResource.java index 01a4f4519..63bf74d0e 100644 --- a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/ITMResource.java +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/ITMResource.java @@ -1,37 +1,41 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.registry; - -import java.io.IOException; -import java.io.InputStream; - -/** - * TextMate resource definition API. - * - */ -public interface ITMResource extends ITMDefinition { - - /** - * Returns the TextMate resource path. - * - * @return the TextMate resource path. - */ - String getPath(); - - /** - * Returns the stream of the TextMate resource. - * - * @return the stream of the TextMate resource. - * @throws IOException - */ - public InputStream getInputStream() throws IOException; -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.registry; + +import java.io.IOException; +import java.io.InputStream; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * TextMate resource definition API. + * + */ +public interface ITMResource extends ITMDefinition { + + /** + * Returns the TextMate resource path. + * + * @return the TextMate resource path. + */ + @Nullable + String getPath(); + + /** + * Returns the stream of the TextMate resource. + * + * @return the stream of the TextMate resource. + * @throws IOException + */ + @Nullable + InputStream getInputStream() throws IOException; +} diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/TMEclipseRegistryPlugin.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/TMEclipseRegistryPlugin.java index 1ebaa1b48..fa4a366e7 100644 --- a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/TMEclipseRegistryPlugin.java +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/TMEclipseRegistryPlugin.java @@ -1,63 +1,65 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.registry; - -import org.eclipse.core.runtime.Platform; -import org.eclipse.tm4e.registry.internal.GrammarRegistryManager; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - -/** - * OSGi Activator for TextMate Eclipse registry bundle. - * - */ -public class TMEclipseRegistryPlugin implements BundleActivator { - - public static final String PLUGIN_ID = "org.eclipse.tm4e.registry"; - - private static BundleContext context; - - static BundleContext getContext() { - return context; - } - - @Override - public void start(BundleContext bundleContext) throws Exception { - TMEclipseRegistryPlugin.context = bundleContext; - } - - @Override - public void stop(BundleContext bundleContext) throws Exception { - TMEclipseRegistryPlugin.context = null; - } - - /** - * Returns the TextMate grammar manager. - * - * @return the TextMate grammar manager. - */ - public static IGrammarRegistryManager getGrammarRegistryManager() { - return GrammarRegistryManager.getInstance(); - } - - /** - * Returns true if the debug option is enabled and false otherwise. - * - * @param option - * the option name - * @return true if the debug option is enabled and false otherwise. - */ - public static boolean isDebugOptionEnabled(String option) { - String enabled = Platform.getDebugOption(option); - return enabled != null && Boolean.parseBoolean(enabled); - } + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.registry; + +import org.eclipse.core.runtime.Platform; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.registry.internal.GrammarRegistryManager; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +/** + * OSGi Activator for TextMate Eclipse registry bundle. + */ +public class TMEclipseRegistryPlugin implements BundleActivator { + + public static final String PLUGIN_ID = "org.eclipse.tm4e.registry"; + + @Nullable + private static BundleContext context; + + @Nullable + static BundleContext getContext() { + return context; + } + + @Override + public void start(@Nullable final BundleContext bundleContext) throws Exception { + TMEclipseRegistryPlugin.context = bundleContext; + } + + @Override + public void stop(@Nullable final BundleContext bundleContext) throws Exception { + TMEclipseRegistryPlugin.context = null; + } + + /** + * Returns the TextMate grammar manager. + * + * @return the TextMate grammar manager. + */ + public static IGrammarRegistryManager getGrammarRegistryManager() { + return GrammarRegistryManager.getInstance(); + } + + /** + * Returns true if the debug option is enabled and false otherwise. + * + * @param option + * the option name + * @return true if the debug option is enabled and false otherwise. + */ + public static boolean isDebugOptionEnabled(final String option) { + final String enabled = Platform.getDebugOption(option); + return enabled != null && Boolean.parseBoolean(enabled); + } } \ No newline at end of file diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/TMResource.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/TMResource.java index 8c4e77a87..62985ff21 100644 --- a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/TMResource.java +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/TMResource.java @@ -1,106 +1,107 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.registry; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Scanner; - -import org.eclipse.core.runtime.IConfigurationElement; - -/** - * TextMate Resource. - */ -public class TMResource implements ITMResource { - - private static final String PLATFORM_PLUGIN = "platform:/plugin/"; //$NON-NLS-1$ - - private String path; - private String pluginId; - - /** - * Constructor for user preferences (loaded from Json with Gson). - */ - public TMResource() { - - } - - /** - * Constructor for extension point. - * - * @param element - */ - public TMResource(String path) { - this.path = path; - } - - public TMResource(IConfigurationElement ce) { - this(ce.getAttribute(XMLConstants.PATH_ATTR)); - this.pluginId = ce.getNamespaceIdentifier(); - } - - public TMResource(String path, String pluginId) { - this.path = path; - this.pluginId = pluginId; - } - - @Override - public String getPath() { - return path; - } - - @Override - public String getPluginId() { - return pluginId; - } - - @Override - public InputStream getInputStream() throws IOException { - if (path == null || path.length() < 0) { - return null; - } - if (pluginId != null) { - URL url = new URL(new StringBuilder(PLATFORM_PLUGIN).append(pluginId).append("/").append(path).toString()); - return url.openStream(); - } - return new FileInputStream(new File(path)); - } - - protected String getResourceContent() { - try { - InputStream in = this.getInputStream(); - if (in == null) { - return null; - } - return convertStreamToString(in); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - private static String convertStreamToString(InputStream is) { - Scanner s = null; - try { - s = new Scanner(is); - s.useDelimiter("\\A"); - return s.hasNext() ? s.next() : ""; - } finally { - if (s != null) { - s.close(); - } - } - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.registry; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Scanner; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.jdt.annotation.Nullable; + +/** + * TextMate Resource. + */ +public class TMResource implements ITMResource { + + private static final String PLATFORM_PLUGIN = "platform:/plugin/"; //$NON-NLS-1$ + + @Nullable + private String path; + + @Nullable + private String pluginId; + + /** + * Constructor for user preferences (loaded from Json with Gson). + */ + public TMResource() { + + } + + /** + * Constructor for extension point. + * + * @param path + */ + public TMResource(final String path) { + this.path = path; + } + + public TMResource(final IConfigurationElement ce) { + this(ce.getAttribute(XMLConstants.PATH_ATTR)); + this.pluginId = ce.getNamespaceIdentifier(); + } + + public TMResource(@Nullable final String path, @Nullable final String pluginId) { + this.path = path; + this.pluginId = pluginId; + } + + @Nullable + @Override + public String getPath() { + return path; + } + + @Nullable + @Override + public String getPluginId() { + return pluginId; + } + + @Nullable + @Override + public InputStream getInputStream() throws IOException { + if (path == null || "".equals(path)) { + return null; + } + if (pluginId != null) { + final URL url = new URL(PLATFORM_PLUGIN + pluginId + "/" + path); + return url.openStream(); + } + return new FileInputStream(new File(path)); + } + + @Nullable + protected String getResourceContent() { + try (InputStream in = this.getInputStream()) { + if (in == null) { + return null; + } + return convertStreamToString(in); + } catch (final Exception e) { + e.printStackTrace(); + } + return null; + } + + private static String convertStreamToString(final InputStream is) { + try (Scanner s = new Scanner(is)) { + s.useDelimiter("\\A"); + return s.hasNext() ? s.next() : ""; + } + } +} diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/WorkingCopyGrammarRegistryManager.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/WorkingCopyGrammarRegistryManager.java index 632e0f507..e55a11127 100644 --- a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/WorkingCopyGrammarRegistryManager.java +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/WorkingCopyGrammarRegistryManager.java @@ -1,95 +1,104 @@ -/** - * Copyright (c) 2015, 2021 Angelo ZERR and others. +/** + * Copyright (c) 2015, 2021 Angelo ZERR and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.registry; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.eclipse.tm4e.registry.internal.AbstractGrammarRegistryManager; -import org.osgi.service.prefs.BackingStoreException; - -/** - * Working copy of grammar registry manager. - * - */ -public class WorkingCopyGrammarRegistryManager extends AbstractGrammarRegistryManager { - - private final IGrammarRegistryManager manager; - - private List added; - - private List removed; - - public WorkingCopyGrammarRegistryManager(IGrammarRegistryManager manager) { - this.manager = manager; - load(); - } - - private void load() { - // Copy grammar definitions - IGrammarDefinition[] definitions = manager.getDefinitions(); - for (IGrammarDefinition definition : definitions) { - super.registerGrammarDefinition(definition); - // Copy binding scope/content types - String scopeName = definition.getScopeName(); - manager.getContentTypesForScope(scopeName).forEach(contentType -> super.registerContentTypeBinding(contentType, scopeName)); - // Copy injection - Collection injections = manager.getInjections(scopeName); - if (injections != null) { - for (String injectFrom : injections) { - super.registerInjection(injectFrom, scopeName); - } - } - } - } - - @Override - public void registerGrammarDefinition(IGrammarDefinition definition) { - super.registerGrammarDefinition(definition); - if (added == null) { - added = new ArrayList<>(); - } - added.add(definition); - } - - @Override - public void unregisterGrammarDefinition(IGrammarDefinition definition) { - super.unregisterGrammarDefinition(definition); - if (added != null && added.contains(definition)) { - added.remove(definition); - } else { - if (removed == null) { - removed = new ArrayList<>(); - } - removed.add(definition); - } - } - - @Override - public void save() throws BackingStoreException { - if (added != null) { - for (IGrammarDefinition definition : added) { - manager.registerGrammarDefinition(definition); - } - } - if (removed != null) { - for (IGrammarDefinition definition : removed) { - manager.unregisterGrammarDefinition(definition); - } - } - if (added != null || removed != null) { - manager.save(); - } - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.registry; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.registry.internal.AbstractGrammarRegistryManager; +import org.osgi.service.prefs.BackingStoreException; + +/** + * Working copy of grammar registry manager. + */ +public class WorkingCopyGrammarRegistryManager extends AbstractGrammarRegistryManager { + + private final IGrammarRegistryManager manager; + + @Nullable + private List added; + + @Nullable + private List removed; + + public WorkingCopyGrammarRegistryManager(final IGrammarRegistryManager manager) { + this.manager = manager; + load(); + } + + private void load() { + // Copy grammar definitions + final IGrammarDefinition[] definitions = manager.getDefinitions(); + for (final IGrammarDefinition definition : definitions) { + super.registerGrammarDefinition(definition); + + // Copy binding scope/content types + final String scopeName = definition.getScopeName(); + final var contentTypes = manager.getContentTypesForScope(scopeName); + if (contentTypes != null) { + contentTypes.forEach(contentType -> super.registerContentTypeBinding(contentType, scopeName)); + } + + // Copy injection + final Collection injections = manager.getInjections(scopeName); + if (injections != null) { + for (final String injectFrom : injections) { + super.registerInjection(injectFrom, scopeName); + } + } + } + } + + @Override + public void registerGrammarDefinition(final IGrammarDefinition definition) { + super.registerGrammarDefinition(definition); + var added = this.added; + if (added == null) { + added = this.added = new ArrayList<>(); + } + added.add(definition); + } + + @Override + public void unregisterGrammarDefinition(final IGrammarDefinition definition) { + super.unregisterGrammarDefinition(definition); + final var added = this.added; + if (added != null && added.contains(definition)) { + added.remove(definition); + } else { + var removed = this.removed; + if (removed == null) { + removed = this.removed = new ArrayList<>(); + } + removed.add(definition); + } + } + + @Override + public void save() throws BackingStoreException { + if (added != null) { + for (final IGrammarDefinition definition : added) { + manager.registerGrammarDefinition(definition); + } + } + if (removed != null) { + for (final IGrammarDefinition definition : removed) { + manager.unregisterGrammarDefinition(definition); + } + } + if (added != null || removed != null) { + manager.save(); + } + } +} diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/XMLConstants.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/XMLConstants.java index 50324c392..631d4b809 100644 --- a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/XMLConstants.java +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/XMLConstants.java @@ -1,37 +1,35 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.registry; - -/** - * XML constants used with the "org.eclipse.tm4e.registry.grammars" extension - * point. - * - */ -public class XMLConstants { - - // grammar definition - public static final String GRAMMAR_ELT = "grammar"; - public static final String NAME_ATTR = "name"; - public static final String SCOPE_NAME_ATTR = "scopeName"; - public static final String PATH_ATTR = "path"; - - // scopeNameContentTypeBinding definition - public static final String SCOPE_NAME_CONTENT_TYPE_BINDING_ELT = "scopeNameContentTypeBinding"; - public static final String CONTENT_TYPE_ID_ATTR = "contentTypeId"; - - // injection definition - public static final String INJECTION_ELT = "injection"; - public static final String INJECT_TO_ATTR = "injectTo"; - - public static final String ID_ATTR = "id"; - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.registry; + +/** + * XML constants used with the "org.eclipse.tm4e.registry.grammars" extension point. + */ +public class XMLConstants { + + // grammar definition + public static final String GRAMMAR_ELT = "grammar"; + public static final String NAME_ATTR = "name"; + public static final String SCOPE_NAME_ATTR = "scopeName"; + public static final String PATH_ATTR = "path"; + + // scopeNameContentTypeBinding definition + public static final String SCOPE_NAME_CONTENT_TYPE_BINDING_ELT = "scopeNameContentTypeBinding"; + public static final String CONTENT_TYPE_ID_ATTR = "contentTypeId"; + + // injection definition + public static final String INJECTION_ELT = "injection"; + public static final String INJECT_TO_ATTR = "injectTo"; + + public static final String ID_ATTR = "id"; + +} diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/AbstractGrammarRegistryManager.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/AbstractGrammarRegistryManager.java index e204b6188..fa3eb692a 100644 --- a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/AbstractGrammarRegistryManager.java +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/AbstractGrammarRegistryManager.java @@ -1,236 +1,228 @@ -/** - * Copyright (c) 2015-2019 Angelo ZERR. +/** + * Copyright (c) 2015-2019 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - * Pierre-Yves B. - Issue #221 NullPointerException when retrieving fileTypes - */ -package org.eclipse.tm4e.registry.internal; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.tm4e.core.grammar.IGrammar; -import org.eclipse.tm4e.core.registry.IRegistryOptions; -import org.eclipse.tm4e.core.registry.Registry; -import org.eclipse.tm4e.registry.IGrammarDefinition; -import org.eclipse.tm4e.registry.IGrammarRegistryManager; - -/** - * Eclipse grammar registry. - * - */ -public abstract class AbstractGrammarRegistryManager extends Registry implements IGrammarRegistryManager { - - protected final GrammarCache pluginCache; - protected final GrammarCache userCache; - - private static class EclipseRegistryOptions implements IRegistryOptions { - - private AbstractGrammarRegistryManager registry; - - public void setRegistry(AbstractGrammarRegistryManager registry) { - this.registry = registry; - } - - @Override - public Collection getInjections(String scopeName) { - return registry.getInjections(scopeName); - } - - @Override - public String getFilePath(String scopeName) { - IGrammarDefinition info = registry.getDefinition(scopeName); - return info != null ? info.getPath() : null; - } - - @Override - public InputStream getInputStream(String scopeName) throws IOException { - IGrammarDefinition info = registry.getDefinition(scopeName); - return info != null ? info.getInputStream() : null; - } - }; - - public AbstractGrammarRegistryManager() { - this(new EclipseRegistryOptions()); - ((EclipseRegistryOptions) getLocator()).setRegistry(this); - } - - public AbstractGrammarRegistryManager(IRegistryOptions locator) { - super(locator); - this.pluginCache = new GrammarCache(); - this.userCache = new GrammarCache(); - } - - @Override - public IGrammar getGrammarFor(IContentType[] contentTypes) { - if (contentTypes == null) { - return null; - } - // Find grammar by content type - for (IContentType contentType : contentTypes) { - String scopeName = getScopeNameForContentType(contentType); - if (scopeName != null) { - IGrammar grammar = getGrammarForScope(scopeName); - if (grammar != null) { - return grammar; - } - } - } - return null; - } - - @Override - public IGrammar getGrammarForScope(String scopeName) { - return getGrammar(scopeName); - } - - @Override - public IGrammar getGrammarForFileType(String fileType) { - // TODO: cache grammar by file types - IGrammarDefinition[] definitions = getDefinitions(); - // #202 - if(fileType.startsWith(".")) { - fileType=fileType.substring(1); - } - for (IGrammarDefinition definition : definitions) { - // Not very optimized because it forces the load of the whole - // grammar. - // Extension Point grammar should perhaps stores file type bindings - // like content type/scope binding? - IGrammar grammar = getGrammarForScope(definition.getScopeName()); - if (grammar != null) { - Collection fileTypes = grammar.getFileTypes(); - if (fileTypes.contains(fileType)) { - return grammar; - } - } - } - return null; - } - - /** - * Returns the whole registered grammar definition. - * - * @return - */ - @Override - public IGrammarDefinition[] getDefinitions() { - Collection pluginDefinitions = pluginCache.getDefinitions(); - Collection userDefinitions = userCache.getDefinitions(); - Collection definitions = new ArrayList<>(pluginDefinitions); - definitions.addAll(userDefinitions); - return definitions.toArray(new IGrammarDefinition[definitions.size()]); - } - - /** - * Returns the loaded grammar from the given scopeName and null - * otherwise. - * - * @param scopeName - * @return the loaded grammar from the given scopeName and null - * otherwise. - */ - public IGrammar getGrammar(String scopeName) { - if (scopeName == null) { - return null; - } - IGrammar grammar = super.grammarForScopeName(scopeName); - if (grammar != null) { - return grammar; - } - return super.loadGrammar(scopeName); - } - - /** - * Returns the grammar definition from the given scopeName and - * null otherwise. - * - * @param scopeName - * @return the grammar definition from the given scopeName and - * null otherwise. - */ - public IGrammarDefinition getDefinition(String scopeName) { - IGrammarDefinition definition = userCache.getDefinition(scopeName); - if (definition != null) { - return definition; - } - return pluginCache.getDefinition(scopeName); - } - - /** - * Returns list of scope names to inject for the given - * scopeName and null otheriwse. - * - * @param scopeName - * @return list of scope names to inject for the given - * scopeName and null otheriwse. - */ - @Override - public Collection getInjections(String scopeName) { - return pluginCache.getInjections(scopeName); - } - - /** - * Register the given scopeName to inject to the given scope - * name injectTo. - * - * @param scopeName - * @param injectTo - */ - public void registerInjection(String scopeName, String injectTo) { - pluginCache.registerInjection(scopeName, injectTo); - } - - /** - * @param contentType - * @return scope name bound with the given content type (or its base type) and - * null otherwise. - */ - public String getScopeNameForContentType(IContentType contentType) { - while (contentType != null) { - String scopeName = pluginCache.getScopeNameForContentType(contentType); - if (scopeName != null) { - return scopeName; - } - contentType = contentType.getBaseType(); - } - return null; - } - - @Override - public List getContentTypesForScope(String scopeName) { - return pluginCache.getContentTypesForScope(scopeName); - } - - public void registerContentTypeBinding(IContentType contentType, String scopeName) { - pluginCache.registerContentTypeBinding(contentType, scopeName); - } - - @Override - public void registerGrammarDefinition(IGrammarDefinition definition) { - if (definition.getPluginId() == null) { - userCache.registerGrammarDefinition(definition); - } else { - pluginCache.registerGrammarDefinition(definition); - } - } - - @Override - public void unregisterGrammarDefinition(IGrammarDefinition definition) { - if (definition.getPluginId() == null) { - userCache.unregisterGrammarDefinition(definition); - } else { - pluginCache.unregisterGrammarDefinition(definition); - } - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + * Pierre-Yves B. - Issue #221 NullPointerException when retrieving fileTypes + */ +package org.eclipse.tm4e.registry.internal; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.core.grammar.IGrammar; +import org.eclipse.tm4e.core.registry.IRegistryOptions; +import org.eclipse.tm4e.core.registry.Registry; +import org.eclipse.tm4e.registry.IGrammarDefinition; +import org.eclipse.tm4e.registry.IGrammarRegistryManager; + +/** + * Eclipse grammar registry. + * + */ +public abstract class AbstractGrammarRegistryManager extends Registry implements IGrammarRegistryManager { + + private final GrammarCache pluginCache; + final GrammarCache userCache; + + private static final class EclipseRegistryOptions implements IRegistryOptions { + + @Nullable + private AbstractGrammarRegistryManager registry; + + private void setRegistry(final AbstractGrammarRegistryManager registry) { + this.registry = registry; + } + + @Nullable + @Override + public Collection getInjections(final String scopeName) { + final var registry = this.registry; + if (registry == null) { + return null; + } + return registry.getInjections(scopeName); + } + + @Nullable + @Override + public String getFilePath(final String scopeName) { + final IGrammarDefinition info = getDefinition(scopeName); + return info != null ? info.getPath() : null; + } + + @Nullable + @Override + public InputStream getInputStream(final String scopeName) throws IOException { + final IGrammarDefinition info = getDefinition(scopeName); + return info != null ? info.getInputStream() : null; + } + + @Nullable + private IGrammarDefinition getDefinition(final String scopeName) { + final var registry = this.registry; + if (registry == null) { + return null; + } + final IGrammarDefinition definition = registry.userCache.getDefinition(scopeName); + if (definition != null) { + return definition; + } + return registry.pluginCache.getDefinition(scopeName); + } + } + + protected AbstractGrammarRegistryManager() { + this(new EclipseRegistryOptions()); + ((EclipseRegistryOptions) getLocator()).setRegistry(this); + } + + protected AbstractGrammarRegistryManager(final IRegistryOptions locator) { + super(locator); + this.pluginCache = new GrammarCache(); + this.userCache = new GrammarCache(); + } + + @Nullable + @Override + public IGrammar getGrammarFor(final IContentType @Nullable [] contentTypes) { + if (contentTypes == null) { + return null; + } + // Find grammar by content type + for (final IContentType contentType : contentTypes) { + final String scopeName = getScopeNameForContentType(contentType); + if (scopeName != null) { + final IGrammar grammar = getGrammarForScope(scopeName); + if (grammar != null) { + return grammar; + } + } + } + return null; + } + + @Nullable + @Override + public IGrammar getGrammarForScope(final String scopeName) { + return getGrammar(scopeName); + } + + @Nullable + @Override + public IGrammar getGrammarForFileType(String fileType) { + // TODO: cache grammar by file types + final IGrammarDefinition[] definitions = getDefinitions(); + // #202 + if (fileType.startsWith(".")) { + fileType = fileType.substring(1); + } + for (final IGrammarDefinition definition : definitions) { + // Not very optimized because it forces the load of the whole + // grammar. + // Extension Point grammar should perhaps stores file type bindings + // like content type/scope binding? + final IGrammar grammar = getGrammarForScope(definition.getScopeName()); + if (grammar != null) { + final Collection fileTypes = grammar.getFileTypes(); + if (fileTypes.contains(fileType)) { + return grammar; + } + } + } + return null; + } + + @Nullable + @Override + public IGrammarDefinition[] getDefinitions() { + final Collection pluginDefinitions = pluginCache.getDefinitions(); + final Collection userDefinitions = userCache.getDefinitions(); + final Collection definitions = new ArrayList<>(pluginDefinitions); + definitions.addAll(userDefinitions); + return definitions.toArray(IGrammarDefinition[]::new); + } + + /** + * Returns the loaded grammar from the given scopeName and null otherwise. + * + * @return the loaded grammar from the given scopeName and null otherwise. + */ + @Nullable + private IGrammar getGrammar(@Nullable final String scopeName) { + if (scopeName == null) { + return null; + } + final IGrammar grammar = super.grammarForScopeName(scopeName); + if (grammar != null) { + return grammar; + } + return super.loadGrammar(scopeName); + } + + @Nullable + @Override + public Collection getInjections(final String scopeName) { + return pluginCache.getInjections(scopeName); + } + + /** + * Register the given scopeName to inject to the given scope name injectTo. + */ + protected void registerInjection(final String scopeName, final String injectTo) { + pluginCache.registerInjection(scopeName, injectTo); + } + + /** + * @return scope name bound with the given content type (or its base type) and null otherwise. + */ + @Nullable + private String getScopeNameForContentType(@Nullable IContentType contentType) { + while (contentType != null) { + final String scopeName = pluginCache.getScopeNameForContentType(contentType); + if (scopeName != null) { + return scopeName; + } + contentType = contentType.getBaseType(); + } + return null; + } + + @Nullable + @Override + public List getContentTypesForScope(final String scopeName) { + return pluginCache.getContentTypesForScope(scopeName); + } + + protected void registerContentTypeBinding(final IContentType contentType, final String scopeName) { + pluginCache.registerContentTypeBinding(contentType, scopeName); + } + + @Override + public void registerGrammarDefinition(final IGrammarDefinition definition) { + if (definition.getPluginId() == null) { + userCache.registerGrammarDefinition(definition); + } else { + pluginCache.registerGrammarDefinition(definition); + } + } + + @Override + public void unregisterGrammarDefinition(final IGrammarDefinition definition) { + if (definition.getPluginId() == null) { + userCache.unregisterGrammarDefinition(definition); + } else { + pluginCache.unregisterGrammarDefinition(definition); + } + } +} diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/GrammarCache.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/GrammarCache.java index 51d8a7cc8..245c3af27 100644 --- a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/GrammarCache.java +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/GrammarCache.java @@ -1,126 +1,112 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.registry.internal; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.stream.Collectors; - -import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.tm4e.registry.IGrammarDefinition; - -/** - * Grammar cache. - * - */ -public class GrammarCache { - - private final Map definitions; - private final Map> injections; - private final Map scopeNameBindings; - - public GrammarCache() { - this.definitions = new HashMap<>(); - this.injections = new HashMap<>(); - this.scopeNameBindings = new HashMap<>(); - } - - /** - * Register a grammar definition. - * - * @param definition - * the grammar definition to register. - */ - public void registerGrammarDefinition(IGrammarDefinition definition) { - definitions.put(definition.getScopeName(), definition); - } - - public void unregisterGrammarDefinition(IGrammarDefinition definition) { - definitions.remove(definition.getScopeName()); - } - - /** - * Returns the whole registered grammar definition. - * - * @return - */ - public Collection getDefinitions() { - return this.definitions.values(); - } - - /** - * Returns the grammar definition from the given scopeName and - * null otherwise. - * - * @param scopeName - * @return the grammar definition from the given scopeName and - * null otherwise. - */ - public IGrammarDefinition getDefinition(String scopeName) { - return definitions.get(scopeName); - } - - /** - * Returns list of scope names to inject for the given - * scopeName and null otheriwse. - * - * @param scopeName - * @return list of scope names to inject for the given - * scopeName and null otheriwse. - */ - public Collection getInjections(String scopeName) { - return injections.get(scopeName); - } - - /** - * Register the given scopeName to inject to the given scope - * name injectTo. - * - * @param scopeName - * @param injectTo - */ - public void registerInjection(String scopeName, String injectTo) { - Collection injections = getInjections(injectTo); - if (injections == null) { - injections = new ArrayList<>(); - this.injections.put(injectTo, injections); - } - injections.add(scopeName); - } - - /** - * Returns scope name bound with the given content type and null otherwise. - * - * @param contentType - * @return scope name bound with the given content type and null otherwise. - */ - public String getScopeNameForContentType(IContentType contentType) { - return scopeNameBindings.get(contentType); - } - - public List getContentTypesForScope(String scopeName) { - if (scopeName == null) { - return List.of(); - } - return scopeNameBindings.entrySet().stream().filter(map -> scopeName.equals(map.getValue())) - .map(Entry::getKey).collect(Collectors.toList()); - } - - public void registerContentTypeBinding(IContentType contentType, String scopeName) { - scopeNameBindings.put(contentType, scopeName); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.registry.internal; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; + +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.registry.IGrammarDefinition; + +/** + * Grammar cache. + */ +final class GrammarCache { + + private final Map definitions = new HashMap<>(); + private final Map> injections = new HashMap<>(); + private final Map scopeNameBindings = new HashMap<>(); + + /** + * Register a grammar definition. + * + * @param definition the grammar definition to register. + */ + void registerGrammarDefinition(final IGrammarDefinition definition) { + definitions.put(definition.getScopeName(), definition); + } + + void unregisterGrammarDefinition(final IGrammarDefinition definition) { + definitions.remove(definition.getScopeName()); + } + + /** + * Returns the whole registered grammar definition. + * + * @return the whole registered grammar definition. + */ + Collection getDefinitions() { + return this.definitions.values(); + } + + /** + * Returns the grammar definition from the given scopeName and null otherwise. + * + * @return the grammar definition from the given scopeName and null otherwise. + */ + @Nullable + IGrammarDefinition getDefinition(final String scopeName) { + return definitions.get(scopeName); + } + + /** + * Returns list of scope names to inject for the given scopeName and null otheriwse. + * + * @return list of scope names to inject for the given scopeName and null otheriwse. + */ + @Nullable + Collection getInjections(final String scopeName) { + return injections.get(scopeName); + } + + /** + * Register the given scopeName to inject to the given scope name injectTo. + */ + void registerInjection(final String scopeName, final String injectTo) { + var injections = getInjections(injectTo); + if (injections == null) { + injections = new ArrayList<>(); + this.injections.put(injectTo, injections); + } + injections.add(scopeName); + } + + /** + * Returns scope name bound with the given content type and null otherwise. + * + * @return scope name bound with the given content type and null otherwise. + */ + @Nullable + String getScopeNameForContentType(final IContentType contentType) { + return scopeNameBindings.get(contentType); + } + + List getContentTypesForScope(@Nullable final String scopeName) { + if (scopeName == null) { + return Collections.emptyList(); + } + + return scopeNameBindings.entrySet().stream().filter(map -> scopeName.equals(map.getValue())) + .map(Entry::getKey).collect(Collectors.toList()); + } + + void registerContentTypeBinding(final IContentType contentType, final String scopeName) { + scopeNameBindings.put(contentType, scopeName); + } +} diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/GrammarRegistryManager.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/GrammarRegistryManager.java index 9ba7d5429..66c94878a 100644 --- a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/GrammarRegistryManager.java +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/GrammarRegistryManager.java @@ -1,114 +1,121 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.registry.internal; - -import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.core.runtime.preferences.IEclipsePreferences; -import org.eclipse.core.runtime.preferences.InstanceScope; -import org.eclipse.tm4e.registry.GrammarDefinition; -import org.eclipse.tm4e.registry.IGrammarDefinition; -import org.eclipse.tm4e.registry.TMEclipseRegistryPlugin; -import org.eclipse.tm4e.registry.XMLConstants; -import org.eclipse.tm4e.registry.internal.preferences.PreferenceConstants; -import org.eclipse.tm4e.registry.internal.preferences.PreferenceHelper; -import org.osgi.service.prefs.BackingStoreException; - -/** - * Grammar registry manager singleton. - */ -public class GrammarRegistryManager extends AbstractGrammarRegistryManager { - - private static final String EXTENSION_GRAMMARS = "grammars"; - - private static GrammarRegistryManager INSTANCE; - - public static GrammarRegistryManager getInstance() { - if (INSTANCE != null) { - return INSTANCE; - } - INSTANCE = createInstance(); - return INSTANCE; - } - - private static synchronized GrammarRegistryManager createInstance() { - if (INSTANCE != null) { - return INSTANCE; - } - GrammarRegistryManager manager = new GrammarRegistryManager(); - manager.load(); - return manager; - } - - private GrammarRegistryManager() { - } - - private void load() { - loadGrammarsFromExtensionPoints(); - loadGrammarsFromPreferences(); - } - - /** - * Load TextMate grammars from extension point. - */ - private void loadGrammarsFromExtensionPoints() { - IConfigurationElement[] cf = Platform.getExtensionRegistry() - .getConfigurationElementsFor(TMEclipseRegistryPlugin.PLUGIN_ID, EXTENSION_GRAMMARS); - for (IConfigurationElement ce : cf) { - String extensionName = ce.getName(); - if (XMLConstants.GRAMMAR_ELT.equals(extensionName)) { - super.registerGrammarDefinition(new GrammarDefinition(ce)); - } else if (XMLConstants.INJECTION_ELT.equals(extensionName)) { - String scopeName = ce.getAttribute(XMLConstants.SCOPE_NAME_ATTR); - String injectTo = ce.getAttribute(XMLConstants.INJECT_TO_ATTR); - super.registerInjection(scopeName, injectTo); - } else if (XMLConstants.SCOPE_NAME_CONTENT_TYPE_BINDING_ELT.equals(extensionName)) { - String contentTypeId = ce.getAttribute(XMLConstants.CONTENT_TYPE_ID_ATTR); - IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeId); - if (contentType == null) { - Platform.getLog(getClass()).warn("No content-type found with id='" + contentTypeId + "', ignoring TM4E association."); - } else { - String scopeName = ce.getAttribute(XMLConstants.SCOPE_NAME_ATTR); - super.registerContentTypeBinding(contentType, scopeName); - } - } - } - } - - /** - * Load TextMate grammars from preferences. - */ - private void loadGrammarsFromPreferences() { - // Load grammar definitions from the - // "${workspace_loc}/metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.tm4e.registry.prefs" - IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(TMEclipseRegistryPlugin.PLUGIN_ID); - String json = prefs.get(PreferenceConstants.GRAMMARS, null); - if (json != null) { - IGrammarDefinition[] definitions = PreferenceHelper.loadGrammars(json); - for (IGrammarDefinition definition : definitions) { - userCache.registerGrammarDefinition(definition); - } - } - } - - @Override - public void save() throws BackingStoreException { - // Save grammar definitions in the - // "${workspace_loc}/metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.tm4e.registry.prefs" - String json = PreferenceHelper.toJson(userCache.getDefinitions()); - IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(TMEclipseRegistryPlugin.PLUGIN_ID); - prefs.put(PreferenceConstants.GRAMMARS, json); - prefs.flush(); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.registry.internal; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.registry.GrammarDefinition; +import org.eclipse.tm4e.registry.IGrammarDefinition; +import org.eclipse.tm4e.registry.TMEclipseRegistryPlugin; +import org.eclipse.tm4e.registry.XMLConstants; +import org.eclipse.tm4e.registry.internal.preferences.PreferenceConstants; +import org.eclipse.tm4e.registry.internal.preferences.PreferenceHelper; +import org.osgi.service.prefs.BackingStoreException; + +/** + * Grammar registry manager singleton. + */ +public final class GrammarRegistryManager extends AbstractGrammarRegistryManager { + + private static final String EXTENSION_GRAMMARS = "grammars"; + + @Nullable + private static GrammarRegistryManager INSTANCE; + + public static GrammarRegistryManager getInstance() { + if (INSTANCE != null) { + return INSTANCE; + } + INSTANCE = createInstance(); + return INSTANCE; + } + + private static synchronized GrammarRegistryManager createInstance() { + if (INSTANCE != null) { + return INSTANCE; + } + final GrammarRegistryManager manager = new GrammarRegistryManager(); + manager.load(); + return manager; + } + + private GrammarRegistryManager() { + } + + private void load() { + loadGrammarsFromExtensionPoints(); + loadGrammarsFromPreferences(); + } + + /** + * Load TextMate grammars from extension point. + */ + private void loadGrammarsFromExtensionPoints() { + final IConfigurationElement[] cf = Platform.getExtensionRegistry() + .getConfigurationElementsFor(TMEclipseRegistryPlugin.PLUGIN_ID, EXTENSION_GRAMMARS); + for (final IConfigurationElement ce : cf) { + final String extensionName = ce.getName(); + switch (extensionName) { + case XMLConstants.GRAMMAR_ELT: + super.registerGrammarDefinition(new GrammarDefinition(ce)); + break; + case XMLConstants.INJECTION_ELT: { + final String scopeName = ce.getAttribute(XMLConstants.SCOPE_NAME_ATTR); + final String injectTo = ce.getAttribute(XMLConstants.INJECT_TO_ATTR); + super.registerInjection(scopeName, injectTo); + break; + } + case XMLConstants.SCOPE_NAME_CONTENT_TYPE_BINDING_ELT: { + final String contentTypeId = ce.getAttribute(XMLConstants.CONTENT_TYPE_ID_ATTR); + final IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeId); + if (contentType == null) { + Platform.getLog(getClass()) + .warn("No content-type found with id='" + contentTypeId + "', ignoring TM4E association."); + } else { + final String scopeName = ce.getAttribute(XMLConstants.SCOPE_NAME_ATTR); + super.registerContentTypeBinding(contentType, scopeName); + } + break; + } + } + } + } + + /** + * Load TextMate grammars from preferences. + */ + private void loadGrammarsFromPreferences() { + // Load grammar definitions from the + // "${workspace_loc}/metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.tm4e.registry.prefs" + final var prefs = InstanceScope.INSTANCE.getNode(TMEclipseRegistryPlugin.PLUGIN_ID); + final var json = prefs.get(PreferenceConstants.GRAMMARS, null); + if (json != null) { + final IGrammarDefinition[] definitions = PreferenceHelper.loadGrammars(json); + for (final IGrammarDefinition definition : definitions) { + userCache.registerGrammarDefinition(definition); + } + } + } + + @Override + public void save() throws BackingStoreException { + // Save grammar definitions in the + // "${workspace_loc}/metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.tm4e.registry.prefs" + final var json = PreferenceHelper.toJson(userCache.getDefinitions()); + final var prefs = InstanceScope.INSTANCE.getNode(TMEclipseRegistryPlugin.PLUGIN_ID); + prefs.put(PreferenceConstants.GRAMMARS, json); + prefs.flush(); + } +} diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/package-info.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/package-info.java new file mode 100644 index 000000000..fd08b8783 --- /dev/null +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.registry.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/preferences/PreferenceConstants.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/preferences/PreferenceConstants.java index c00d93274..530efd756 100644 --- a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/preferences/PreferenceConstants.java +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/preferences/PreferenceConstants.java @@ -1,26 +1,27 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.registry.internal.preferences; - -/** - * Preferences constants for grammar. - * - */ -public class PreferenceConstants { - - public static final String GRAMMARS = "org.eclipse.tm4e.registry.grammars"; - - public static final String SCOPE_NAME_CONTENTTYPE_BINDINGS = "org.eclipse.tm4e.registry.scopeNameContentTypeBindings"; - - public static final String INJECTIONS = "org.eclipse.tm4e.registry.injections"; - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.registry.internal.preferences; + +/** + * Preferences constants for grammar. + */ +public final class PreferenceConstants { + + public static final String GRAMMARS = "org.eclipse.tm4e.registry.grammars"; + + public static final String SCOPE_NAME_CONTENTTYPE_BINDINGS = "org.eclipse.tm4e.registry.scopeNameContentTypeBindings"; + + public static final String INJECTIONS = "org.eclipse.tm4e.registry.injections"; + + private PreferenceConstants() { + } +} diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/preferences/PreferenceHelper.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/preferences/PreferenceHelper.java index 2f3a6952b..d7e6a46d0 100644 --- a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/preferences/PreferenceHelper.java +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/preferences/PreferenceHelper.java @@ -1,50 +1,44 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.registry.internal.preferences; - -import java.lang.reflect.Type; -import java.util.Collection; - -import org.eclipse.tm4e.registry.GrammarDefinition; -import org.eclipse.tm4e.registry.IGrammarDefinition; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.InstanceCreator; - -/** - * Helper class load, save grammar preferences with Json format. - * - */ -public class PreferenceHelper { - - private static final Gson DEFAULT_GSON; - - static { - DEFAULT_GSON = new GsonBuilder() - .registerTypeAdapter(IGrammarDefinition.class, new InstanceCreator() { - @Override - public GrammarDefinition createInstance(Type type) { - return new GrammarDefinition(); - } - }).create(); - } - - public static IGrammarDefinition[] loadGrammars(String json) { - return DEFAULT_GSON.fromJson(json, GrammarDefinition[].class); - } - - public static String toJson(Collection definitions) { - return DEFAULT_GSON.toJson(definitions); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.registry.internal.preferences; + +import java.util.Collection; + +import org.eclipse.tm4e.registry.GrammarDefinition; +import org.eclipse.tm4e.registry.IGrammarDefinition; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.InstanceCreator; + +/** + * Helper class load, save grammar preferences with Json format. + * + */ +public final class PreferenceHelper { + + private static final Gson DEFAULT_GSON = new GsonBuilder() + .registerTypeAdapter(IGrammarDefinition.class, + (InstanceCreator) type -> new GrammarDefinition()) + .create(); + + public static IGrammarDefinition[] loadGrammars(final String json) { + return DEFAULT_GSON.fromJson(json, GrammarDefinition[].class); + } + + public static String toJson(final Collection definitions) { + return DEFAULT_GSON.toJson(definitions); + } + + private PreferenceHelper() { + } +} diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/preferences/package-info.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/preferences/package-info.java new file mode 100644 index 000000000..78207bf75 --- /dev/null +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/internal/preferences/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.registry.internal.preferences; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/package-info.java b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/package-info.java new file mode 100644 index 000000000..069f47ac3 --- /dev/null +++ b/org.eclipse.tm4e.registry/src/main/java/org/eclipse/tm4e/registry/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.registry; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui.tests/src/test/resources/.gitkeep b/org.eclipse.tm4e.registry/src/main/resources/.gitkeep similarity index 100% rename from org.eclipse.tm4e.ui.tests/src/test/resources/.gitkeep rename to org.eclipse.tm4e.registry/src/main/resources/.gitkeep diff --git a/org.eclipse.tm4e.repository/.gitignore b/org.eclipse.tm4e.repository/.gitignore deleted file mode 100644 index b83d22266..000000000 --- a/org.eclipse.tm4e.repository/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/org.eclipse.tm4e.repository/pom.xml b/org.eclipse.tm4e.repository/pom.xml index d903e9b9c..283537b4e 100644 --- a/org.eclipse.tm4e.repository/pom.xml +++ b/org.eclipse.tm4e.repository/pom.xml @@ -1,53 +1,31 @@ - 4.0.0 - org.eclipse.tm4e.repository - eclipse-repository - - org.eclipse - org.eclipse.tm4e - 0.3.2-SNAPSHOT - - - - - - org.apache.maven.wagon - wagon-ftp - 3.4.3 - - - + 4.0.0 + org.eclipse.tm4e.repository + eclipse-repository + + org.eclipse + org.eclipse.tm4e + 0.3.2-SNAPSHOT + + - - uploadRepo - - - ftp://ftp.online.net - /oss/textmate/${project.version} - - ${project.build.directory}/repository/ - - - - - - org.codehaus.mojo - wagon-maven-plugin - 2.0.2 + sign + + + + org.eclipse.tycho + tycho-gpg-plugin + ${tycho-version} - upload-repo - install + pgpsigner - upload + sign-p2-artifacts - ${repo.path} - ** - ${ftp.toDir} - ${ftp.url} - p2Repo + 27617A05E2DB057F + true @@ -55,33 +33,5 @@ - - release - - - - de.jutzig - github-release-plugin - 1.4.0 - - - github-upload - verify - - release - - false - - - - true - ${project.artifactId}-${project.version} - ${project.artifactId}-${project.version} - ${project.build.directory}/${project.artifactId}-${project.version}.zip - - - - - \ No newline at end of file diff --git a/org.eclipse.tm4e.samples/.gitignore b/org.eclipse.tm4e.samples/.gitignore deleted file mode 100644 index 934e0e06f..000000000 --- a/org.eclipse.tm4e.samples/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/bin -/target diff --git a/org.eclipse.tm4e.samples/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.tm4e.samples/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..f648802b5 --- /dev/null +++ b/org.eclipse.tm4e.samples/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,518 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.APILeak=warning +org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning +org.eclipse.jdt.core.compiler.problem.fallthroughCase=info +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=info +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=enabled +org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=11 +org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false +org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false +org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter=0 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type=49 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assertion_message=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0 +org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_record_components=16 +org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_type_annotations=0 +org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0 +org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch=0 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_constructor=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false +org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true +org.eclipse.jdt.core.formatter.comment.format_block_comments=false +org.eclipse.jdt.core.formatter.comment.format_header=true +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.indent_tag_description=false +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=120 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_not_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false +org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.text_block_indentation=0 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false +org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true +org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true +org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true +org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true +org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/org.eclipse.tm4e.samples/META-INF/MANIFEST.MF b/org.eclipse.tm4e.samples/META-INF/MANIFEST.MF index c4426f2fd..3a8a53abf 100644 --- a/org.eclipse.tm4e.samples/META-INF/MANIFEST.MF +++ b/org.eclipse.tm4e.samples/META-INF/MANIFEST.MF @@ -4,7 +4,7 @@ Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-Localization: plugin Bundle-SymbolicName: org.eclipse.tm4e.samples;singleton:=true -Bundle-Version: 0.3.6.qualifier +Bundle-Version: 0.3.7.qualifier Require-Bundle: org.eclipse.jface.text, org.eclipse.core.runtime, org.eclipse.ui, diff --git a/org.eclipse.tm4e.samples/pom.xml b/org.eclipse.tm4e.samples/pom.xml index d302e4f6c..66422b70b 100644 --- a/org.eclipse.tm4e.samples/pom.xml +++ b/org.eclipse.tm4e.samples/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.eclipse.tm4e.samples eclipse-plugin - 0.3.6-SNAPSHOT + 0.3.7-SNAPSHOT org.eclipse org.eclipse.tm4e diff --git a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/TMSamplesPlugin.java b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/TMSamplesPlugin.java index 130c98ab8..0a0c3843b 100644 --- a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/TMSamplesPlugin.java +++ b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/TMSamplesPlugin.java @@ -1,78 +1,78 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.samples; - -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.ui.plugin.AbstractUIPlugin; -import org.osgi.framework.BundleContext; - -/** - * The activator class controls the plug-in life cycle - */ -public class TMSamplesPlugin extends AbstractUIPlugin { - - // The plug-in ID - public static final String PLUGIN_ID = "org.eclipse.tm4e.samples"; //$NON-NLS-1$ - - // The shared instance - private static TMSamplesPlugin plugin; - - /** - * The constructor - */ - public TMSamplesPlugin() { - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework. - * BundleContext) - */ - public void start(BundleContext context) throws Exception { - super.start(context); - plugin = this; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework. - * BundleContext) - */ - public void stop(BundleContext context) throws Exception { - plugin = null; - super.stop(context); - } - - /** - * Returns the shared instance - * - * @return the shared instance - */ - public static TMSamplesPlugin getDefault() { - return plugin; - } - - /** - * Returns an image descriptor for the image file at the given plug-in - * relative path - * - * @param path - * the path - * @return the image descriptor - */ - public static ImageDescriptor getImageDescriptor(String path) { - return imageDescriptorFromPlugin(PLUGIN_ID, path); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.samples; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class TMSamplesPlugin extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.tm4e.samples"; //$NON-NLS-1$ + + // The shared instance + private static TMSamplesPlugin plugin; + + /** + * The constructor + */ + public TMSamplesPlugin() { + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework. + * BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework. + * BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static TMSamplesPlugin getDefault() { + return plugin; + } + + /** + * Returns an image descriptor for the image file at the given plug-in + * relative path + * + * @param path + * the path + * @return the image descriptor + */ + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } + +} diff --git a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/angular2/Angular2Editor.java b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/angular2/Angular2Editor.java index 2a824ff64..610a92fbe 100644 --- a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/angular2/Angular2Editor.java +++ b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/angular2/Angular2Editor.java @@ -1,21 +1,21 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.samples.angular2; - -import org.eclipse.ui.editors.text.TextEditor; - -public class Angular2Editor extends TextEditor { - - public Angular2Editor() { - setSourceViewerConfiguration(new Angular2ViewerConfiguration()); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.samples.angular2; + +import org.eclipse.ui.editors.text.TextEditor; + +public class Angular2Editor extends TextEditor { + + public Angular2Editor() { + setSourceViewerConfiguration(new Angular2ViewerConfiguration()); + } +} diff --git a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/angular2/Angular2ViewerConfiguration.java b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/angular2/Angular2ViewerConfiguration.java index 4b115d321..b8725b001 100644 --- a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/angular2/Angular2ViewerConfiguration.java +++ b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/angular2/Angular2ViewerConfiguration.java @@ -1,68 +1,68 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.samples.angular2; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Collection; - -import org.eclipse.jface.text.presentation.IPresentationReconciler; -import org.eclipse.jface.text.source.ISourceViewer; -import org.eclipse.jface.text.source.SourceViewerConfiguration; -import org.eclipse.tm4e.core.grammar.IGrammar; -import org.eclipse.tm4e.core.registry.IRegistryOptions; -import org.eclipse.tm4e.core.registry.Registry; -import org.eclipse.tm4e.ui.text.TMPresentationReconciler; - -public class Angular2ViewerConfiguration extends SourceViewerConfiguration { - - @Override - public IPresentationReconciler getPresentationReconciler(ISourceViewer viewer) { - // Defines a TextMate Presentation reconcilier - TMPresentationReconciler reconciler = new TMPresentationReconciler(); - // Set the Angular2 grammar - reconciler.setGrammar(getGrammar()); - return reconciler; - } - - private IGrammar getGrammar() { - Registry registry = new Registry(new IRegistryOptions() { - - @Override - public InputStream getInputStream(String scopeName) throws IOException { - return Angular2ViewerConfiguration.class.getResourceAsStream(getFilePath(scopeName)); - } - - @Override - public Collection getInjections(String scopeName) { - return Arrays.asList("template.ng", "styles.ng", "source.ng.css"); - } - - @Override - public String getFilePath(String scopeName) { -// if ("source.ng.css".equals(scopeName)) { -// return "source.ng.css.json"; -// } else if ("source.ng.ts".equals(scopeName)) { -// return "source.ng.ts.json"; -// } else if ("template.ng".equals(scopeName)) { -// return "template.ng.json"; -// } else if ("styles.ng".equals(scopeName)) { -// return "styles.ng.json"; -// } - return scopeName + ".json"; - } - }); - return registry.loadGrammar("source.ng.ts"); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.samples.angular2; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collection; + +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.tm4e.core.grammar.IGrammar; +import org.eclipse.tm4e.core.registry.IRegistryOptions; +import org.eclipse.tm4e.core.registry.Registry; +import org.eclipse.tm4e.ui.text.TMPresentationReconciler; + +public class Angular2ViewerConfiguration extends SourceViewerConfiguration { + + @Override + public IPresentationReconciler getPresentationReconciler(ISourceViewer viewer) { + // Defines a TextMate Presentation reconcilier + TMPresentationReconciler reconciler = new TMPresentationReconciler(); + // Set the Angular2 grammar + reconciler.setGrammar(getGrammar()); + return reconciler; + } + + private IGrammar getGrammar() { + Registry registry = new Registry(new IRegistryOptions() { + + @Override + public InputStream getInputStream(String scopeName) throws IOException { + return Angular2ViewerConfiguration.class.getResourceAsStream(getFilePath(scopeName)); + } + + @Override + public Collection getInjections(String scopeName) { + return Arrays.asList("template.ng", "styles.ng", "source.ng.css"); + } + + @Override + public String getFilePath(String scopeName) { +// if ("source.ng.css".equals(scopeName)) { +// return "source.ng.css.json"; +// } else if ("source.ng.ts".equals(scopeName)) { +// return "source.ng.ts.json"; +// } else if ("template.ng".equals(scopeName)) { +// return "template.ng.json"; +// } else if ("styles.ng".equals(scopeName)) { +// return "styles.ng.json"; +// } + return scopeName + ".json"; + } + }); + return registry.loadGrammar("source.ng.ts"); + } + +} diff --git a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/freemarker/FreemarkerEditor.java b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/freemarker/FreemarkerEditor.java index f6a40edad..a83903b8d 100644 --- a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/freemarker/FreemarkerEditor.java +++ b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/freemarker/FreemarkerEditor.java @@ -1,21 +1,21 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.samples.freemarker; - -import org.eclipse.ui.editors.text.TextEditor; - -public class FreemarkerEditor extends TextEditor { - - public FreemarkerEditor() { - setSourceViewerConfiguration(new FreemarkerViewerConfiguration()); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.samples.freemarker; + +import org.eclipse.ui.editors.text.TextEditor; + +public class FreemarkerEditor extends TextEditor { + + public FreemarkerEditor() { + setSourceViewerConfiguration(new FreemarkerViewerConfiguration()); + } +} diff --git a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/freemarker/FreemarkerViewerConfiguration.java b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/freemarker/FreemarkerViewerConfiguration.java index cae4cf76b..efd0ccad2 100644 --- a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/freemarker/FreemarkerViewerConfiguration.java +++ b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/freemarker/FreemarkerViewerConfiguration.java @@ -1,27 +1,27 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.samples.freemarker; - -import org.eclipse.jface.text.presentation.IPresentationReconciler; -import org.eclipse.jface.text.source.ISourceViewer; -import org.eclipse.jface.text.source.SourceViewerConfiguration; -import org.eclipse.tm4e.ui.text.TMPresentationReconciler; - -public class FreemarkerViewerConfiguration extends SourceViewerConfiguration { - - @Override - public IPresentationReconciler getPresentationReconciler(ISourceViewer viewer) { - // Defines a TextMate Presentation reconcilier - return new TMPresentationReconciler(); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.samples.freemarker; + +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.tm4e.ui.text.TMPresentationReconciler; + +public class FreemarkerViewerConfiguration extends SourceViewerConfiguration { + + @Override + public IPresentationReconciler getPresentationReconciler(ISourceViewer viewer) { + // Defines a TextMate Presentation reconcilier + return new TMPresentationReconciler(); + } + +} diff --git a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/html/HTMLEditor.java b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/html/HTMLEditor.java index 613e8a2f6..a116e5f08 100644 --- a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/html/HTMLEditor.java +++ b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/html/HTMLEditor.java @@ -1,21 +1,21 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.samples.html; - -import org.eclipse.ui.editors.text.TextEditor; - -public class HTMLEditor extends TextEditor { - - public HTMLEditor() { - setSourceViewerConfiguration(new HTMLViewerConfiguration()); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.samples.html; + +import org.eclipse.ui.editors.text.TextEditor; + +public class HTMLEditor extends TextEditor { + + public HTMLEditor() { + setSourceViewerConfiguration(new HTMLViewerConfiguration()); + } +} diff --git a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/html/HTMLViewerConfiguration.java b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/html/HTMLViewerConfiguration.java index 2f4b11b57..e5945d684 100644 --- a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/html/HTMLViewerConfiguration.java +++ b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/html/HTMLViewerConfiguration.java @@ -1,27 +1,27 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.samples.html; - -import org.eclipse.jface.text.presentation.IPresentationReconciler; -import org.eclipse.jface.text.source.ISourceViewer; -import org.eclipse.jface.text.source.SourceViewerConfiguration; -import org.eclipse.tm4e.ui.text.TMPresentationReconciler; - -public class HTMLViewerConfiguration extends SourceViewerConfiguration { - - @Override - public IPresentationReconciler getPresentationReconciler(ISourceViewer viewer) { - // Defines a TextMate Presentation reconcilier - return new TMPresentationReconciler(); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.samples.html; + +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.tm4e.ui.text.TMPresentationReconciler; + +public class HTMLViewerConfiguration extends SourceViewerConfiguration { + + @Override + public IPresentationReconciler getPresentationReconciler(ISourceViewer viewer) { + // Defines a TextMate Presentation reconcilier + return new TMPresentationReconciler(); + } + +} diff --git a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/php/PHPEditor.java b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/php/PHPEditor.java index f053200c0..d5c1ab426 100644 --- a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/php/PHPEditor.java +++ b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/php/PHPEditor.java @@ -1,21 +1,21 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.samples.php; - -import org.eclipse.ui.editors.text.TextEditor; - -public class PHPEditor extends TextEditor { - - public PHPEditor() { - setSourceViewerConfiguration(new PHPViewerConfiguration()); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.samples.php; + +import org.eclipse.ui.editors.text.TextEditor; + +public class PHPEditor extends TextEditor { + + public PHPEditor() { + setSourceViewerConfiguration(new PHPViewerConfiguration()); + } +} diff --git a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/php/PHPViewerConfiguration.java b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/php/PHPViewerConfiguration.java index 665e30531..5eb3ed598 100644 --- a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/php/PHPViewerConfiguration.java +++ b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/php/PHPViewerConfiguration.java @@ -1,27 +1,27 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.samples.php; - -import org.eclipse.jface.text.presentation.IPresentationReconciler; -import org.eclipse.jface.text.source.ISourceViewer; -import org.eclipse.jface.text.source.SourceViewerConfiguration; -import org.eclipse.tm4e.ui.text.TMPresentationReconciler; - -public class PHPViewerConfiguration extends SourceViewerConfiguration { - - @Override - public IPresentationReconciler getPresentationReconciler(ISourceViewer viewer) { - // Defines a TextMate Presentation reconcilier - return new TMPresentationReconciler(); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.samples.php; + +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.tm4e.ui.text.TMPresentationReconciler; + +public class PHPViewerConfiguration extends SourceViewerConfiguration { + + @Override + public IPresentationReconciler getPresentationReconciler(ISourceViewer viewer) { + // Defines a TextMate Presentation reconcilier + return new TMPresentationReconciler(); + } + +} diff --git a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/typescript/JSXEditor.java b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/typescript/JSXEditor.java index 85fde4765..5288e1026 100644 --- a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/typescript/JSXEditor.java +++ b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/typescript/JSXEditor.java @@ -1,21 +1,21 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.samples.typescript; - -import org.eclipse.ui.editors.text.TextEditor; - -public class JSXEditor extends TextEditor { - - public JSXEditor() { - setSourceViewerConfiguration(new JSXViewerConfiguration()); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.samples.typescript; + +import org.eclipse.ui.editors.text.TextEditor; + +public class JSXEditor extends TextEditor { + + public JSXEditor() { + setSourceViewerConfiguration(new JSXViewerConfiguration()); + } +} diff --git a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/typescript/JSXViewerConfiguration.java b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/typescript/JSXViewerConfiguration.java index 346863028..0590f857a 100644 --- a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/typescript/JSXViewerConfiguration.java +++ b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/typescript/JSXViewerConfiguration.java @@ -1,44 +1,44 @@ -/** - * Copyright (c) 2015-2018 Angelo ZERR. +/** + * Copyright (c) 2015-2018 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.samples.typescript; - -import org.eclipse.jface.text.presentation.IPresentationReconciler; -import org.eclipse.jface.text.source.ISourceViewer; -import org.eclipse.jface.text.source.SourceViewerConfiguration; -import org.eclipse.tm4e.core.grammar.IGrammar; -import org.eclipse.tm4e.core.registry.Registry; -import org.eclipse.tm4e.ui.text.TMPresentationReconciler; - -public class JSXViewerConfiguration extends SourceViewerConfiguration { - - @Override - public IPresentationReconciler getPresentationReconciler(ISourceViewer viewer) { - // Defines a TextMate Presentation reconcilier - TMPresentationReconciler reconciler = new TMPresentationReconciler(); - // Set the TypeScript grammar - reconciler.setGrammar(getGrammar()); - return reconciler; - } - - private IGrammar getGrammar() { - // TODO: cache the grammar - Registry registry = new Registry(); - try { - return registry.loadGrammarFromPathSync("TypeScriptReact.tmLanguage.json", - JSXViewerConfiguration.class.getResourceAsStream("TypeScriptReact.tmLanguage.json")); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.samples.typescript; + +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.tm4e.core.grammar.IGrammar; +import org.eclipse.tm4e.core.registry.Registry; +import org.eclipse.tm4e.ui.text.TMPresentationReconciler; + +public class JSXViewerConfiguration extends SourceViewerConfiguration { + + @Override + public IPresentationReconciler getPresentationReconciler(ISourceViewer viewer) { + // Defines a TextMate Presentation reconcilier + TMPresentationReconciler reconciler = new TMPresentationReconciler(); + // Set the TypeScript grammar + reconciler.setGrammar(getGrammar()); + return reconciler; + } + + private IGrammar getGrammar() { + // TODO: cache the grammar + Registry registry = new Registry(); + try { + return registry.loadGrammarFromPathSync("TypeScriptReact.tmLanguage.json", + JSXViewerConfiguration.class.getResourceAsStream("TypeScriptReact.tmLanguage.json")); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + +} diff --git a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/typescript/TypeScriptEditor.java b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/typescript/TypeScriptEditor.java index c95852dae..e18201811 100644 --- a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/typescript/TypeScriptEditor.java +++ b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/typescript/TypeScriptEditor.java @@ -1,21 +1,21 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.samples.typescript; - -import org.eclipse.ui.editors.text.TextEditor; - -public class TypeScriptEditor extends TextEditor { - - public TypeScriptEditor() { - setSourceViewerConfiguration(new TypeScriptViewerConfiguration()); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.samples.typescript; + +import org.eclipse.ui.editors.text.TextEditor; + +public class TypeScriptEditor extends TextEditor { + + public TypeScriptEditor() { + setSourceViewerConfiguration(new TypeScriptViewerConfiguration()); + } +} diff --git a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/typescript/TypeScriptViewerConfiguration.java b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/typescript/TypeScriptViewerConfiguration.java index d4617a846..2a6385a5d 100644 --- a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/typescript/TypeScriptViewerConfiguration.java +++ b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/typescript/TypeScriptViewerConfiguration.java @@ -1,45 +1,45 @@ -/** - * Copyright (c) 2015-2018 Angelo ZERR. +/** + * Copyright (c) 2015-2018 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.samples.typescript; - -import org.eclipse.jface.text.presentation.IPresentationReconciler; -import org.eclipse.jface.text.source.ISourceViewer; -import org.eclipse.jface.text.source.SourceViewerConfiguration; -import org.eclipse.tm4e.core.grammar.IGrammar; -import org.eclipse.tm4e.core.registry.Registry; -import org.eclipse.tm4e.ui.text.TMPresentationReconciler; - -public class TypeScriptViewerConfiguration extends SourceViewerConfiguration { - - @Override - public IPresentationReconciler getPresentationReconciler(ISourceViewer viewer) { - // Defines a TextMate Presentation reconcilier - TMPresentationReconciler reconciler = new TMPresentationReconciler(); - // Set the TypeScript grammar - reconciler.setGrammar(getGrammar()); - //reconciler.setThemeId(ThemeIdConstants.Monokai); - return reconciler; - } - - private IGrammar getGrammar() { - // TODO: cache the grammar - Registry registry = new Registry(); - try { - return registry.loadGrammarFromPathSync("TypeScript.tmLanguage.json", - TypeScriptViewerConfiguration.class.getResourceAsStream("TypeScript.tmLanguage.json")); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.samples.typescript; + +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.tm4e.core.grammar.IGrammar; +import org.eclipse.tm4e.core.registry.Registry; +import org.eclipse.tm4e.ui.text.TMPresentationReconciler; + +public class TypeScriptViewerConfiguration extends SourceViewerConfiguration { + + @Override + public IPresentationReconciler getPresentationReconciler(ISourceViewer viewer) { + // Defines a TextMate Presentation reconcilier + TMPresentationReconciler reconciler = new TMPresentationReconciler(); + // Set the TypeScript grammar + reconciler.setGrammar(getGrammar()); + //reconciler.setThemeId(ThemeIdConstants.Monokai); + return reconciler; + } + + private IGrammar getGrammar() { + // TODO: cache the grammar + Registry registry = new Registry(); + try { + return registry.loadGrammarFromPathSync("TypeScript.tmLanguage.json", + TypeScriptViewerConfiguration.class.getResourceAsStream("TypeScript.tmLanguage.json")); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + +} diff --git a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/yaml/YAMLEditor.java b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/yaml/YAMLEditor.java index 12011c34c..a2ae224df 100644 --- a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/yaml/YAMLEditor.java +++ b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/yaml/YAMLEditor.java @@ -1,21 +1,21 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.samples.yaml; - -import org.eclipse.ui.editors.text.TextEditor; - -public class YAMLEditor extends TextEditor { - - public YAMLEditor() { - setSourceViewerConfiguration(new YAMLViewerConfiguration()); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.samples.yaml; + +import org.eclipse.ui.editors.text.TextEditor; + +public class YAMLEditor extends TextEditor { + + public YAMLEditor() { + setSourceViewerConfiguration(new YAMLViewerConfiguration()); + } +} diff --git a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/yaml/YAMLViewerConfiguration.java b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/yaml/YAMLViewerConfiguration.java index adff61b92..907adaadb 100644 --- a/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/yaml/YAMLViewerConfiguration.java +++ b/org.eclipse.tm4e.samples/src/main/java/org/eclipse/tm4e/samples/yaml/YAMLViewerConfiguration.java @@ -1,27 +1,27 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.samples.yaml; - -import org.eclipse.jface.text.presentation.IPresentationReconciler; -import org.eclipse.jface.text.source.ISourceViewer; -import org.eclipse.jface.text.source.SourceViewerConfiguration; -import org.eclipse.tm4e.ui.text.TMPresentationReconciler; - -public class YAMLViewerConfiguration extends SourceViewerConfiguration { - - @Override - public IPresentationReconciler getPresentationReconciler(ISourceViewer viewer) { - // Defines a TextMate Presentation reconcilier - return new TMPresentationReconciler(); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.samples.yaml; + +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.tm4e.ui.text.TMPresentationReconciler; + +public class YAMLViewerConfiguration extends SourceViewerConfiguration { + + @Override + public IPresentationReconciler getPresentationReconciler(ISourceViewer viewer) { + // Defines a TextMate Presentation reconcilier + return new TMPresentationReconciler(); + } + +} diff --git a/org.eclipse.tm4e.samples/syntaxes/YAML.tmLanguage b/org.eclipse.tm4e.samples/syntaxes/YAML.tmLanguage index 175f45d7b..63f85b8f9 100644 --- a/org.eclipse.tm4e.samples/syntaxes/YAML.tmLanguage +++ b/org.eclipse.tm4e.samples/syntaxes/YAML.tmLanguage @@ -1,1164 +1,1164 @@ - - - - - fileTypes - - yaml - yml - rviz - reek - clang-format - yaml-tmlanguage - syntax - sublime-syntax - - firstLineMatch - ^%YAML( ?1.\d+)? - keyEquivalent - ^~Y - name - YAML - patterns - - - include - #comment - - - include - #property - - - include - #directive - - - match - ^--- - name - entity.other.document.begin.yaml - - - match - ^\.{3} - name - entity.other.document.end.yaml - - - include - #node - - - repository - - block-collection - - patterns - - - include - #block-sequence - - - include - #block-mapping - - - - block-mapping - - patterns - - - include - #block-pair - - - - block-node - - patterns - - - include - #prototype - - - include - #block-scalar - - - include - #block-collection - - - include - #flow-scalar-plain-out - - - include - #flow-node - - - - block-pair - - patterns - - - begin - \? - beginCaptures - - 1 - - name - punctuation.definition.key-value.begin.yaml - - - end - (?=\?)|^ *(:)|(:) - endCaptures - - 1 - - name - punctuation.separator.key-value.mapping.yaml - - 2 - - name - invalid.illegal.expected-newline.yaml - - - name - meta.block-mapping.yaml - patterns - - - include - #block-node - - - - - begin - (?x) - (?= - (?x: - [^\s[-?:,\[\]{}#&*!|>'"%@`]] - | [?:-] \S - ) - ( - [^\s:] - | : \S - | \s+ (?![#\s]) - )* - \s* - : - (\s|$) - ) - - end - (?x) - (?= - \s* $ - | \s+ \# - | \s* : (\s|$) - ) - - patterns - - - include - #flow-scalar-plain-out-implicit-type - - - begin - (?x) - [^\s[-?:,\[\]{}#&*!|>'"%@`]] - | [?:-] \S - - beginCaptures - - 0 - - name - entity.name.tag.yaml - - - contentName - entity.name.tag.yaml - end - (?x) - (?= - \s* $ - | \s+ \# - | \s* : (\s|$) - ) - - name - string.unquoted.plain.out.yaml - - - - - match - :(?=\s|$) - name - punctuation.separator.key-value.mapping.yaml - - - - block-scalar - - begin - (?:(\|)|(>))([1-9])?([-+])?(.*\n?) - beginCaptures - - 1 - - name - punctuation.definition.block.scalar.literal.yaml - - 2 - - name - punctuation.definition.block.scalar.folded.yaml - - 3 - - name - constant.numeric.indentation-indicator.yaml - - 4 - - name - support.other.chomping-indicator.yaml - - 5 - - patterns - - - include - #comment - - - match - .+ - name - invalid.illegal.expected-comment-or-newline.yaml - - - - - end - ^(?=\S)|(?!\G) - patterns - - - begin - ^([ ]+)(?! ) - end - ^(?!\1|\s*$) - name - string.unquoted.block.yaml - - - - block-sequence - - match - (-)( |\t|$) - name - punctuation.definition.block.sequence.item.yaml - - comment - - begin - (?:(^[ \t]*)|[ \t]+)(?=#\p{Print}*$) - beginCaptures - - 1 - - name - punctuation.whitespace.comment.leading.yaml - - - end - (?!\G) - patterns - - - begin - # - beginCaptures - - 0 - - name - punctuation.definition.comment.yaml - - - end - \n - name - comment.line.number-sign.yaml - - - - directive - - begin - ^% - beginCaptures - - 0 - - name - punctuation.definition.directive.begin.yaml - - - end - (?=$|[ \t]+($|#)) - name - meta.directive.yaml - patterns - - - captures - - 1 - - name - keyword.other.directive.yaml.yaml - - 2 - - name - constant.numeric.yaml-version.yaml - - - match - \G(YAML)[ \t]+(\d+\.\d+) - - - captures - - 1 - - name - keyword.other.directive.tag.yaml - - 2 - - name - storage.type.tag-handle.yaml - - 3 - - name - support.type.tag-prefix.yaml - - - match - (?x) - \G - (TAG) - (?:[ \t]+ - ((?:!(?:[0-9A-Za-z\-]*!)?)) - (?:[ \t]+ ( - ! (?x: %\p{XDigit}{2} | [0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]] )* - | (?![,!\[\]{}]) (?x: %\p{XDigit}{2} | [0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]] )+ - ) - )? - )? - - - - captures - - 1 - - name - support.other.directive.reserved.yaml - - 2 - - name - string.unquoted.directive-name.yaml - - 3 - - name - string.unquoted.directive-parameter.yaml - - - match - (?x) \G (\w+) (?:[ \t]+ (\w+) (?:[ \t]+ (\w+))? )? - - - match - \S+ - name - invalid.illegal.unrecognized.yaml - - - - flow-alias - - captures - - 1 - - name - keyword.control.flow.alias.yaml - - 2 - - name - punctuation.definition.alias.yaml - - 3 - - name - variable.other.alias.yaml - - 4 - - name - invalid.illegal.character.anchor.yaml - - - match - ((\*))([^\s\[\]/{/},]+)([^\s\]},]\S*)? - - flow-collection - - patterns - - - include - #flow-sequence - - - include - #flow-mapping - - - - flow-mapping - - begin - \{ - beginCaptures - - 0 - - name - punctuation.definition.mapping.begin.yaml - - - end - \} - endCaptures - - 0 - - name - punctuation.definition.mapping.end.yaml - - - name - meta.flow-mapping.yaml - patterns - - - include - #prototype - - - match - , - name - punctuation.separator.mapping.yaml - - - include - #flow-pair - - - - flow-node - - patterns - - - include - #prototype - - - include - #flow-alias - - - include - #flow-collection - - - include - #flow-scalar - - - - flow-pair - - patterns - - - begin - \? - beginCaptures - - 0 - - name - punctuation.definition.key-value.begin.yaml - - - end - (?=[},\]]) - name - meta.flow-pair.explicit.yaml - patterns - - - include - #prototype - - - include - #flow-pair - - - include - #flow-node - - - begin - :(?=\s|$|[\[\]{},]) - beginCaptures - - 0 - - name - punctuation.separator.key-value.mapping.yaml - - - end - (?=[},\]]) - patterns - - - include - #flow-value - - - - - - - begin - (?x) - (?= - (?: - [^\s[-?:,\[\]{}#&*!|>'"%@`]] - | [?:-] [^\s[\[\]{},]] - ) - ( - [^\s:[\[\]{},]] - | : [^\s[\[\]{},]] - | \s+ (?![#\s]) - )* - \s* - : - (\s|$) - ) - - end - (?x) - (?= - \s* $ - | \s+ \# - | \s* : (\s|$) - | \s* : [\[\]{},] - | \s* [\[\]{},] - ) - - name - meta.flow-pair.key.yaml - patterns - - - include - #flow-scalar-plain-in-implicit-type - - - begin - (?x) - [^\s[-?:,\[\]{}#&*!|>'"%@`]] - | [?:-] [^\s[\[\]{},]] - - beginCaptures - - 0 - - name - entity.name.tag.yaml - - - contentName - entity.name.tag.yaml - end - (?x) - (?= - \s* $ - | \s+ \# - | \s* : (\s|$) - | \s* : [\[\]{},] - | \s* [\[\]{},] - ) - - name - string.unquoted.plain.in.yaml - - - - - include - #flow-node - - - begin - :(?=\s|$|[\[\]{},]) - captures - - 0 - - name - punctuation.separator.key-value.mapping.yaml - - - end - (?=[},\]]) - name - meta.flow-pair.yaml - patterns - - - include - #flow-value - - - - - - flow-scalar - - patterns - - - include - #flow-scalar-double-quoted - - - include - #flow-scalar-single-quoted - - - include - #flow-scalar-plain-in - - - - flow-scalar-double-quoted - - begin - " - beginCaptures - - 0 - - name - punctuation.definition.string.begin.yaml - - - end - " - endCaptures - - 0 - - name - punctuation.definition.string.end.yaml - - - name - string.quoted.double.yaml - patterns - - - match - \\([0abtnvfre "/\\N_Lp]|x\d\d|u\d{4}|U\d{8}) - name - constant.character.escape.yaml - - - match - \\\n - name - constant.character.escape.double-quoted.newline.yaml - - - - flow-scalar-plain-in - - patterns - - - include - #flow-scalar-plain-in-implicit-type - - - begin - (?x) - [^\s[-?:,\[\]{}#&*!|>'"%@`]] - | [?:-] [^\s[\[\]{},]] - - end - (?x) - (?= - \s* $ - | \s+ \# - | \s* : (\s|$) - | \s* : [\[\]{},] - | \s* [\[\]{},] - ) - - name - string.unquoted.plain.in.yaml - - - - flow-scalar-plain-in-implicit-type - - patterns - - - captures - - 1 - - name - constant.language.null.yaml - - 2 - - name - constant.language.boolean.yaml - - 3 - - name - constant.numeric.integer.yaml - - 4 - - name - constant.numeric.float.yaml - - 5 - - name - constant.other.timestamp.yaml - - 6 - - name - constant.language.value.yaml - - 7 - - name - constant.language.merge.yaml - - - match - (?x) - (?x: - (null|Null|NULL|~) - | (y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF) - | ( - (?: - [-+]? 0b [0-1_]+ # (base 2) - | [-+]? 0 [0-7_]+ # (base 8) - | [-+]? (?: 0|[1-9][0-9_]*) # (base 10) - | [-+]? 0x [0-9a-fA-F_]+ # (base 16) - | [-+]? [1-9] [0-9_]* (?: :[0-5]?[0-9])+ # (base 60) - ) - ) - | ( - (?x: - [-+]? (?: [0-9] [0-9_]*)? \. [0-9.]* (?: [eE] [-+] [0-9]+)? # (base 10) - | [-+]? [0-9] [0-9_]* (?: :[0-5]?[0-9])+ \. [0-9_]* # (base 60) - | [-+]? \. (?: inf|Inf|INF) # (infinity) - | \. (?: nan|NaN|NAN) # (not a number) - ) - ) - | ( - (?x: - \d{4} - \d{2} - \d{2} # (y-m-d) - | \d{4} # (year) - - \d{1,2} # (month) - - \d{1,2} # (day) - (?: [Tt] | [ \t]+) \d{1,2} # (hour) - : \d{2} # (minute) - : \d{2} # (second) - (?: \.\d*)? # (fraction) - (?: - (?:[ \t]*) Z - | [-+] \d{1,2} (?: :\d{1,2})? - )? # (time zone) - ) - ) - | (=) - | (<<) - ) - (?: - (?= - \s* $ - | \s+ \# - | \s* : (\s|$) - | \s* : [\[\]{},] - | \s* [\[\]{},] - ) - ) - - - - - flow-scalar-plain-out - - patterns - - - include - #flow-scalar-plain-out-implicit-type - - - begin - (?x) - [^\s[-?:,\[\]{}#&*!|>'"%@`]] - | [?:-] \S - - end - (?x) - (?= - \s* $ - | \s+ \# - | \s* : (\s|$) - ) - - name - string.unquoted.plain.out.yaml - - - - flow-scalar-plain-out-implicit-type - - patterns - - - captures - - 1 - - name - constant.language.null.yaml - - 2 - - name - constant.language.boolean.yaml - - 3 - - name - constant.numeric.integer.yaml - - 4 - - name - constant.numeric.float.yaml - - 5 - - name - constant.other.timestamp.yaml - - 6 - - name - constant.language.value.yaml - - 7 - - name - constant.language.merge.yaml - - - match - (?x) - (?x: - (null|Null|NULL|~) - | (y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF) - | ( - (?: - [-+]? 0b [0-1_]+ # (base 2) - | [-+]? 0 [0-7_]+ # (base 8) - | [-+]? (?: 0|[1-9][0-9_]*) # (base 10) - | [-+]? 0x [0-9a-fA-F_]+ # (base 16) - | [-+]? [1-9] [0-9_]* (?: :[0-5]?[0-9])+ # (base 60) - ) - ) - | ( - (?x: - [-+]? (?: [0-9] [0-9_]*)? \. [0-9.]* (?: [eE] [-+] [0-9]+)? # (base 10) - | [-+]? [0-9] [0-9_]* (?: :[0-5]?[0-9])+ \. [0-9_]* # (base 60) - | [-+]? \. (?: inf|Inf|INF) # (infinity) - | \. (?: nan|NaN|NAN) # (not a number) - ) - ) - | ( - (?x: - \d{4} - \d{2} - \d{2} # (y-m-d) - | \d{4} # (year) - - \d{1,2} # (month) - - \d{1,2} # (day) - (?: [Tt] | [ \t]+) \d{1,2} # (hour) - : \d{2} # (minute) - : \d{2} # (second) - (?: \.\d*)? # (fraction) - (?: - (?:[ \t]*) Z - | [-+] \d{1,2} (?: :\d{1,2})? - )? # (time zone) - ) - ) - | (=) - | (<<) - ) - (?x: - (?= - \s* $ - | \s+ \# - | \s* : (\s|$) - ) - ) - - - - - flow-scalar-single-quoted - - begin - ' - beginCaptures - - 0 - - name - punctuation.definition.string.begin.yaml - - - end - '(?!') - endCaptures - - 0 - - name - punctuation.definition.string.end.yaml - - - name - string.quoted.single.yaml - patterns - - - match - '' - name - constant.character.escape.single-quoted.yaml - - - - flow-sequence - - begin - \[ - beginCaptures - - 0 - - name - punctuation.definition.sequence.begin.yaml - - - end - \] - endCaptures - - 0 - - name - punctuation.definition.sequence.end.yaml - - - name - meta.flow-sequence.yaml - patterns - - - include - #prototype - - - match - , - name - punctuation.separator.sequence.yaml - - - include - #flow-pair - - - include - #flow-node - - - - flow-value - - patterns - - - begin - \G(?![},\]]) - end - (?=[},\]]) - name - meta.flow-pair.value.yaml - patterns - - - include - #flow-node - - - - - - node - - patterns - - - include - #block-node - - - - property - - begin - (?=!|&) - end - (?!\G) - name - meta.property.yaml - patterns - - - captures - - 1 - - name - keyword.control.property.anchor.yaml - - 2 - - name - punctuation.definition.anchor.yaml - - 3 - - name - entity.name.type.anchor.yaml - - 4 - - name - invalid.illegal.character.anchor.yaml - - - match - \G((&))([^\s\[\]/{/},]+)(\S+)? - - - match - (?x) - \G - (?: - ! < (?: %\p{XDigit}{2} | [0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]] )+ > - | (?:!(?:[0-9A-Za-z\-]*!)?) (?: %\p{XDigit}{2} | [0-9A-Za-z\-#;/?:@&=+$_.~*'()] )+ - | ! - ) - (?=\ |\t|$) - - name - storage.type.tag-handle.yaml - - - match - \S+ - name - invalid.illegal.tag-handle.yaml - - - - prototype - - patterns - - - include - #comment - - - include - #property - - - - - scopeName - source.yaml - uuid - 686AD6AE-33F3-4493-9512-9E9FC1D5417F - + + + + + fileTypes + + yaml + yml + rviz + reek + clang-format + yaml-tmlanguage + syntax + sublime-syntax + + firstLineMatch + ^%YAML( ?1.\d+)? + keyEquivalent + ^~Y + name + YAML + patterns + + + include + #comment + + + include + #property + + + include + #directive + + + match + ^--- + name + entity.other.document.begin.yaml + + + match + ^\.{3} + name + entity.other.document.end.yaml + + + include + #node + + + repository + + block-collection + + patterns + + + include + #block-sequence + + + include + #block-mapping + + + + block-mapping + + patterns + + + include + #block-pair + + + + block-node + + patterns + + + include + #prototype + + + include + #block-scalar + + + include + #block-collection + + + include + #flow-scalar-plain-out + + + include + #flow-node + + + + block-pair + + patterns + + + begin + \? + beginCaptures + + 1 + + name + punctuation.definition.key-value.begin.yaml + + + end + (?=\?)|^ *(:)|(:) + endCaptures + + 1 + + name + punctuation.separator.key-value.mapping.yaml + + 2 + + name + invalid.illegal.expected-newline.yaml + + + name + meta.block-mapping.yaml + patterns + + + include + #block-node + + + + + begin + (?x) + (?= + (?x: + [^\s[-?:,\[\]{}#&*!|>'"%@`]] + | [?:-] \S + ) + ( + [^\s:] + | : \S + | \s+ (?![#\s]) + )* + \s* + : + (\s|$) + ) + + end + (?x) + (?= + \s* $ + | \s+ \# + | \s* : (\s|$) + ) + + patterns + + + include + #flow-scalar-plain-out-implicit-type + + + begin + (?x) + [^\s[-?:,\[\]{}#&*!|>'"%@`]] + | [?:-] \S + + beginCaptures + + 0 + + name + entity.name.tag.yaml + + + contentName + entity.name.tag.yaml + end + (?x) + (?= + \s* $ + | \s+ \# + | \s* : (\s|$) + ) + + name + string.unquoted.plain.out.yaml + + + + + match + :(?=\s|$) + name + punctuation.separator.key-value.mapping.yaml + + + + block-scalar + + begin + (?:(\|)|(>))([1-9])?([-+])?(.*\n?) + beginCaptures + + 1 + + name + punctuation.definition.block.scalar.literal.yaml + + 2 + + name + punctuation.definition.block.scalar.folded.yaml + + 3 + + name + constant.numeric.indentation-indicator.yaml + + 4 + + name + support.other.chomping-indicator.yaml + + 5 + + patterns + + + include + #comment + + + match + .+ + name + invalid.illegal.expected-comment-or-newline.yaml + + + + + end + ^(?=\S)|(?!\G) + patterns + + + begin + ^([ ]+)(?! ) + end + ^(?!\1|\s*$) + name + string.unquoted.block.yaml + + + + block-sequence + + match + (-)( |\t|$) + name + punctuation.definition.block.sequence.item.yaml + + comment + + begin + (?:(^[ \t]*)|[ \t]+)(?=#\p{Print}*$) + beginCaptures + + 1 + + name + punctuation.whitespace.comment.leading.yaml + + + end + (?!\G) + patterns + + + begin + # + beginCaptures + + 0 + + name + punctuation.definition.comment.yaml + + + end + \n + name + comment.line.number-sign.yaml + + + + directive + + begin + ^% + beginCaptures + + 0 + + name + punctuation.definition.directive.begin.yaml + + + end + (?=$|[ \t]+($|#)) + name + meta.directive.yaml + patterns + + + captures + + 1 + + name + keyword.other.directive.yaml.yaml + + 2 + + name + constant.numeric.yaml-version.yaml + + + match + \G(YAML)[ \t]+(\d+\.\d+) + + + captures + + 1 + + name + keyword.other.directive.tag.yaml + + 2 + + name + storage.type.tag-handle.yaml + + 3 + + name + support.type.tag-prefix.yaml + + + match + (?x) + \G + (TAG) + (?:[ \t]+ + ((?:!(?:[0-9A-Za-z\-]*!)?)) + (?:[ \t]+ ( + ! (?x: %\p{XDigit}{2} | [0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]] )* + | (?![,!\[\]{}]) (?x: %\p{XDigit}{2} | [0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]] )+ + ) + )? + )? + + + + captures + + 1 + + name + support.other.directive.reserved.yaml + + 2 + + name + string.unquoted.directive-name.yaml + + 3 + + name + string.unquoted.directive-parameter.yaml + + + match + (?x) \G (\w+) (?:[ \t]+ (\w+) (?:[ \t]+ (\w+))? )? + + + match + \S+ + name + invalid.illegal.unrecognized.yaml + + + + flow-alias + + captures + + 1 + + name + keyword.control.flow.alias.yaml + + 2 + + name + punctuation.definition.alias.yaml + + 3 + + name + variable.other.alias.yaml + + 4 + + name + invalid.illegal.character.anchor.yaml + + + match + ((\*))([^\s\[\]/{/},]+)([^\s\]},]\S*)? + + flow-collection + + patterns + + + include + #flow-sequence + + + include + #flow-mapping + + + + flow-mapping + + begin + \{ + beginCaptures + + 0 + + name + punctuation.definition.mapping.begin.yaml + + + end + \} + endCaptures + + 0 + + name + punctuation.definition.mapping.end.yaml + + + name + meta.flow-mapping.yaml + patterns + + + include + #prototype + + + match + , + name + punctuation.separator.mapping.yaml + + + include + #flow-pair + + + + flow-node + + patterns + + + include + #prototype + + + include + #flow-alias + + + include + #flow-collection + + + include + #flow-scalar + + + + flow-pair + + patterns + + + begin + \? + beginCaptures + + 0 + + name + punctuation.definition.key-value.begin.yaml + + + end + (?=[},\]]) + name + meta.flow-pair.explicit.yaml + patterns + + + include + #prototype + + + include + #flow-pair + + + include + #flow-node + + + begin + :(?=\s|$|[\[\]{},]) + beginCaptures + + 0 + + name + punctuation.separator.key-value.mapping.yaml + + + end + (?=[},\]]) + patterns + + + include + #flow-value + + + + + + + begin + (?x) + (?= + (?: + [^\s[-?:,\[\]{}#&*!|>'"%@`]] + | [?:-] [^\s[\[\]{},]] + ) + ( + [^\s:[\[\]{},]] + | : [^\s[\[\]{},]] + | \s+ (?![#\s]) + )* + \s* + : + (\s|$) + ) + + end + (?x) + (?= + \s* $ + | \s+ \# + | \s* : (\s|$) + | \s* : [\[\]{},] + | \s* [\[\]{},] + ) + + name + meta.flow-pair.key.yaml + patterns + + + include + #flow-scalar-plain-in-implicit-type + + + begin + (?x) + [^\s[-?:,\[\]{}#&*!|>'"%@`]] + | [?:-] [^\s[\[\]{},]] + + beginCaptures + + 0 + + name + entity.name.tag.yaml + + + contentName + entity.name.tag.yaml + end + (?x) + (?= + \s* $ + | \s+ \# + | \s* : (\s|$) + | \s* : [\[\]{},] + | \s* [\[\]{},] + ) + + name + string.unquoted.plain.in.yaml + + + + + include + #flow-node + + + begin + :(?=\s|$|[\[\]{},]) + captures + + 0 + + name + punctuation.separator.key-value.mapping.yaml + + + end + (?=[},\]]) + name + meta.flow-pair.yaml + patterns + + + include + #flow-value + + + + + + flow-scalar + + patterns + + + include + #flow-scalar-double-quoted + + + include + #flow-scalar-single-quoted + + + include + #flow-scalar-plain-in + + + + flow-scalar-double-quoted + + begin + " + beginCaptures + + 0 + + name + punctuation.definition.string.begin.yaml + + + end + " + endCaptures + + 0 + + name + punctuation.definition.string.end.yaml + + + name + string.quoted.double.yaml + patterns + + + match + \\([0abtnvfre "/\\N_Lp]|x\d\d|u\d{4}|U\d{8}) + name + constant.character.escape.yaml + + + match + \\\n + name + constant.character.escape.double-quoted.newline.yaml + + + + flow-scalar-plain-in + + patterns + + + include + #flow-scalar-plain-in-implicit-type + + + begin + (?x) + [^\s[-?:,\[\]{}#&*!|>'"%@`]] + | [?:-] [^\s[\[\]{},]] + + end + (?x) + (?= + \s* $ + | \s+ \# + | \s* : (\s|$) + | \s* : [\[\]{},] + | \s* [\[\]{},] + ) + + name + string.unquoted.plain.in.yaml + + + + flow-scalar-plain-in-implicit-type + + patterns + + + captures + + 1 + + name + constant.language.null.yaml + + 2 + + name + constant.language.boolean.yaml + + 3 + + name + constant.numeric.integer.yaml + + 4 + + name + constant.numeric.float.yaml + + 5 + + name + constant.other.timestamp.yaml + + 6 + + name + constant.language.value.yaml + + 7 + + name + constant.language.merge.yaml + + + match + (?x) + (?x: + (null|Null|NULL|~) + | (y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF) + | ( + (?: + [-+]? 0b [0-1_]+ # (base 2) + | [-+]? 0 [0-7_]+ # (base 8) + | [-+]? (?: 0|[1-9][0-9_]*) # (base 10) + | [-+]? 0x [0-9a-fA-F_]+ # (base 16) + | [-+]? [1-9] [0-9_]* (?: :[0-5]?[0-9])+ # (base 60) + ) + ) + | ( + (?x: + [-+]? (?: [0-9] [0-9_]*)? \. [0-9.]* (?: [eE] [-+] [0-9]+)? # (base 10) + | [-+]? [0-9] [0-9_]* (?: :[0-5]?[0-9])+ \. [0-9_]* # (base 60) + | [-+]? \. (?: inf|Inf|INF) # (infinity) + | \. (?: nan|NaN|NAN) # (not a number) + ) + ) + | ( + (?x: + \d{4} - \d{2} - \d{2} # (y-m-d) + | \d{4} # (year) + - \d{1,2} # (month) + - \d{1,2} # (day) + (?: [Tt] | [ \t]+) \d{1,2} # (hour) + : \d{2} # (minute) + : \d{2} # (second) + (?: \.\d*)? # (fraction) + (?: + (?:[ \t]*) Z + | [-+] \d{1,2} (?: :\d{1,2})? + )? # (time zone) + ) + ) + | (=) + | (<<) + ) + (?: + (?= + \s* $ + | \s+ \# + | \s* : (\s|$) + | \s* : [\[\]{},] + | \s* [\[\]{},] + ) + ) + + + + + flow-scalar-plain-out + + patterns + + + include + #flow-scalar-plain-out-implicit-type + + + begin + (?x) + [^\s[-?:,\[\]{}#&*!|>'"%@`]] + | [?:-] \S + + end + (?x) + (?= + \s* $ + | \s+ \# + | \s* : (\s|$) + ) + + name + string.unquoted.plain.out.yaml + + + + flow-scalar-plain-out-implicit-type + + patterns + + + captures + + 1 + + name + constant.language.null.yaml + + 2 + + name + constant.language.boolean.yaml + + 3 + + name + constant.numeric.integer.yaml + + 4 + + name + constant.numeric.float.yaml + + 5 + + name + constant.other.timestamp.yaml + + 6 + + name + constant.language.value.yaml + + 7 + + name + constant.language.merge.yaml + + + match + (?x) + (?x: + (null|Null|NULL|~) + | (y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF) + | ( + (?: + [-+]? 0b [0-1_]+ # (base 2) + | [-+]? 0 [0-7_]+ # (base 8) + | [-+]? (?: 0|[1-9][0-9_]*) # (base 10) + | [-+]? 0x [0-9a-fA-F_]+ # (base 16) + | [-+]? [1-9] [0-9_]* (?: :[0-5]?[0-9])+ # (base 60) + ) + ) + | ( + (?x: + [-+]? (?: [0-9] [0-9_]*)? \. [0-9.]* (?: [eE] [-+] [0-9]+)? # (base 10) + | [-+]? [0-9] [0-9_]* (?: :[0-5]?[0-9])+ \. [0-9_]* # (base 60) + | [-+]? \. (?: inf|Inf|INF) # (infinity) + | \. (?: nan|NaN|NAN) # (not a number) + ) + ) + | ( + (?x: + \d{4} - \d{2} - \d{2} # (y-m-d) + | \d{4} # (year) + - \d{1,2} # (month) + - \d{1,2} # (day) + (?: [Tt] | [ \t]+) \d{1,2} # (hour) + : \d{2} # (minute) + : \d{2} # (second) + (?: \.\d*)? # (fraction) + (?: + (?:[ \t]*) Z + | [-+] \d{1,2} (?: :\d{1,2})? + )? # (time zone) + ) + ) + | (=) + | (<<) + ) + (?x: + (?= + \s* $ + | \s+ \# + | \s* : (\s|$) + ) + ) + + + + + flow-scalar-single-quoted + + begin + ' + beginCaptures + + 0 + + name + punctuation.definition.string.begin.yaml + + + end + '(?!') + endCaptures + + 0 + + name + punctuation.definition.string.end.yaml + + + name + string.quoted.single.yaml + patterns + + + match + '' + name + constant.character.escape.single-quoted.yaml + + + + flow-sequence + + begin + \[ + beginCaptures + + 0 + + name + punctuation.definition.sequence.begin.yaml + + + end + \] + endCaptures + + 0 + + name + punctuation.definition.sequence.end.yaml + + + name + meta.flow-sequence.yaml + patterns + + + include + #prototype + + + match + , + name + punctuation.separator.sequence.yaml + + + include + #flow-pair + + + include + #flow-node + + + + flow-value + + patterns + + + begin + \G(?![},\]]) + end + (?=[},\]]) + name + meta.flow-pair.value.yaml + patterns + + + include + #flow-node + + + + + + node + + patterns + + + include + #block-node + + + + property + + begin + (?=!|&) + end + (?!\G) + name + meta.property.yaml + patterns + + + captures + + 1 + + name + keyword.control.property.anchor.yaml + + 2 + + name + punctuation.definition.anchor.yaml + + 3 + + name + entity.name.type.anchor.yaml + + 4 + + name + invalid.illegal.character.anchor.yaml + + + match + \G((&))([^\s\[\]/{/},]+)(\S+)? + + + match + (?x) + \G + (?: + ! < (?: %\p{XDigit}{2} | [0-9A-Za-z\-#;/?:@&=+$,_.!~*'()\[\]] )+ > + | (?:!(?:[0-9A-Za-z\-]*!)?) (?: %\p{XDigit}{2} | [0-9A-Za-z\-#;/?:@&=+$_.~*'()] )+ + | ! + ) + (?=\ |\t|$) + + name + storage.type.tag-handle.yaml + + + match + \S+ + name + invalid.illegal.tag-handle.yaml + + + + prototype + + patterns + + + include + #comment + + + include + #property + + + + + scopeName + source.yaml + uuid + 686AD6AE-33F3-4493-9512-9E9FC1D5417F + \ No newline at end of file diff --git a/org.eclipse.tm4e.samples/syntaxes/ftl.tmLanguage b/org.eclipse.tm4e.samples/syntaxes/ftl.tmLanguage index 735880650..9be988de3 100644 --- a/org.eclipse.tm4e.samples/syntaxes/ftl.tmLanguage +++ b/org.eclipse.tm4e.samples/syntaxes/ftl.tmLanguage @@ -1,147 +1,147 @@ - - - - - fileTypes - - ftl - - foldingStartMarker - (?x) - (<(?i:head|body|table|thead|tbody|tfoot|tr|div|nav|section|aside|header|select|fieldset|style|script|ul|ol|form|dl)\b.*?> - |<!--(?!.*-->) - |\{\s*($|\?>\s*$|//|/\*(.*\*/\s*$|(?!.*?\*/))) - |(\[|<)(\#|@)\w+.*\(\]|>) - ) - foldingStopMarker - (?x) - (</(?i:head|body|table|thead|tbody|tfoot|tr|div|nav|section|aside|header|select|fieldset|style|script|ul|ol|form|dl)> - |^\s*--> - |(^|\s)\} - |(\[|<)/(\#|@)\w+.*(\]|>) - ) - keyEquivalent - ^~F - name - FreeMarker - patterns - - - begin - [<\[]#-- - captures - - 0 - - name - punctuation.definition.comment.ftl - - - end - --[>\]] - name - comment.block.ftl - - - captures - - 1 - - name - punctuation.definition.function.ftl - - 2 - - name - punctuation.definition.function.ftl - - 3 - - name - entity.name.function.ftl - - 5 - - name - variable.parameter.function.ftl - - 8 - - name - entity.name.function.ftl - - 9 - - name - punctuation.definition.function.ftl - - - match - ([<\[](#|@))(\w+(\.\w+)*)((\s+[^>\]]+)*?)\s*((\/)?([>\]])) - name - meta.function.ftl - - - captures - - 1 - - name - punctuation.definition.function.ftl - - 2 - - name - punctuation.definition.function.ftl - - 3 - - name - entity.name.function.ftl - - 5 - - name - punctuation.definition.function.ftl - - - match - ([<\[]\/(#|@))(\w+(\.\w+)*)\s*([>\]]) - name - meta.function.ftl - - - captures - - 1 - - name - punctuation.definition.variable.ftl - - 3 - - name - entity.name.function.ftl - - 4 - - name - punctuation.definition.variable.ftl - - - match - (\$\{)\.?[a-zA-Z_\(][\w\(\)+-\/\*]+(\.?[\w\(\)+-\/\*]+)*(.*?|\?\?|\!)?(\}) - name - variable.other.readwrite.local.ftl - - - include - text.html.basic - - - scopeName - text.html.ftl - uuid - C011BB07-875D-4DEB-9582-0E1FEC0D1E4E - + + + + + fileTypes + + ftl + + foldingStartMarker + (?x) + (<(?i:head|body|table|thead|tbody|tfoot|tr|div|nav|section|aside|header|select|fieldset|style|script|ul|ol|form|dl)\b.*?> + |<!--(?!.*-->) + |\{\s*($|\?>\s*$|//|/\*(.*\*/\s*$|(?!.*?\*/))) + |(\[|<)(\#|@)\w+.*\(\]|>) + ) + foldingStopMarker + (?x) + (</(?i:head|body|table|thead|tbody|tfoot|tr|div|nav|section|aside|header|select|fieldset|style|script|ul|ol|form|dl)> + |^\s*--> + |(^|\s)\} + |(\[|<)/(\#|@)\w+.*(\]|>) + ) + keyEquivalent + ^~F + name + FreeMarker + patterns + + + begin + [<\[]#-- + captures + + 0 + + name + punctuation.definition.comment.ftl + + + end + --[>\]] + name + comment.block.ftl + + + captures + + 1 + + name + punctuation.definition.function.ftl + + 2 + + name + punctuation.definition.function.ftl + + 3 + + name + entity.name.function.ftl + + 5 + + name + variable.parameter.function.ftl + + 8 + + name + entity.name.function.ftl + + 9 + + name + punctuation.definition.function.ftl + + + match + ([<\[](#|@))(\w+(\.\w+)*)((\s+[^>\]]+)*?)\s*((\/)?([>\]])) + name + meta.function.ftl + + + captures + + 1 + + name + punctuation.definition.function.ftl + + 2 + + name + punctuation.definition.function.ftl + + 3 + + name + entity.name.function.ftl + + 5 + + name + punctuation.definition.function.ftl + + + match + ([<\[]\/(#|@))(\w+(\.\w+)*)\s*([>\]]) + name + meta.function.ftl + + + captures + + 1 + + name + punctuation.definition.variable.ftl + + 3 + + name + entity.name.function.ftl + + 4 + + name + punctuation.definition.variable.ftl + + + match + (\$\{)\.?[a-zA-Z_\(][\w\(\)+-\/\*]+(\.?[\w\(\)+-\/\*]+)*(.*?|\?\?|\!)?(\}) + name + variable.other.readwrite.local.ftl + + + include + text.html.basic + + + scopeName + text.html.ftl + uuid + C011BB07-875D-4DEB-9582-0E1FEC0D1E4E + \ No newline at end of file diff --git a/org.eclipse.tm4e.ui.tests/.classpath b/org.eclipse.tm4e.ui.tests/.classpath index 880118339..71f21812a 100644 --- a/org.eclipse.tm4e.ui.tests/.classpath +++ b/org.eclipse.tm4e.ui.tests/.classpath @@ -6,19 +6,21 @@
    - + - + - + + - + + - + - + diff --git a/org.eclipse.tm4e.ui.tests/.gitignore b/org.eclipse.tm4e.ui.tests/.gitignore deleted file mode 100644 index 934e0e06f..000000000 --- a/org.eclipse.tm4e.ui.tests/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/bin -/target diff --git a/org.eclipse.tm4e.ui.tests/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.tm4e.ui.tests/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..f648802b5 --- /dev/null +++ b/org.eclipse.tm4e.ui.tests/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,518 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.APILeak=warning +org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning +org.eclipse.jdt.core.compiler.problem.fallthroughCase=info +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=info +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=enabled +org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=11 +org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false +org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false +org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter=0 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type=49 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assertion_message=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0 +org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_record_components=16 +org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_type_annotations=0 +org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0 +org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch=0 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_constructor=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false +org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true +org.eclipse.jdt.core.formatter.comment.format_block_comments=false +org.eclipse.jdt.core.formatter.comment.format_header=true +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.indent_tag_description=false +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=120 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_not_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false +org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.text_block_indentation=0 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false +org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true +org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true +org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true +org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true +org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/org.eclipse.tm4e.ui.tests/build.properties b/org.eclipse.tm4e.ui.tests/build.properties index 44774ac89..3fd0f106d 100644 --- a/org.eclipse.tm4e.ui.tests/build.properties +++ b/org.eclipse.tm4e.ui.tests/build.properties @@ -1,10 +1,8 @@ -source.. = src/main/resources/,\ - src/test/java/,\ - src/test/resources/ +source.. = src/main/java/,\ + src/main/resources/ bin.includes = META-INF/,\ .,\ plugin.properties,\ grammars/,\ plugin.xml,\ about.html - diff --git a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/RegistryTest.java b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/RegistryTest.java similarity index 91% rename from org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/RegistryTest.java rename to org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/RegistryTest.java index 87fbde3c1..cbc7efe43 100644 --- a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/RegistryTest.java +++ b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/RegistryTest.java @@ -18,17 +18,17 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -public class RegistryTest { +class RegistryTest { @Test - public void testGrammarRegistered() { + void testGrammarRegistered() { IContentType contentType = Platform.getContentTypeManager().getContentType("org.eclipse.tm4e.ui.tests.testContentType"); IGrammar grammar = TMEclipseRegistryPlugin.getGrammarRegistryManager().getGrammarFor(new IContentType[] { contentType }); Assertions.assertNotNull(grammar); } @Test - public void testThemeAppliesToSubtypes() { + void testThemeAppliesToSubtypes() { IContentType contentType = Platform.getContentTypeManager().getContentType("org.eclipse.tm4e.ui.tests.testContentType.child"); IGrammar grammar = TMEclipseRegistryPlugin.getGrammarRegistryManager().getGrammarFor(new IContentType[] { contentType }); Assertions.assertNotNull(grammar); diff --git a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/TMinGenericEditorTest.java b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/TMinGenericEditorTest.java similarity index 60% rename from org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/TMinGenericEditorTest.java rename to org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/TMinGenericEditorTest.java index cae38c362..7ee2bcec3 100644 --- a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/TMinGenericEditorTest.java +++ b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/TMinGenericEditorTest.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015, 2022 Angelo ZERR and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -12,14 +12,11 @@ package org.eclipse.tm4e.ui; import static org.junit.jupiter.api.Assertions.*; -import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; +import java.util.stream.Collectors; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.widgets.Control; @@ -35,28 +32,41 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class TMinGenericEditorTest { +class TMinGenericEditorTest { private IEditorDescriptor editorDescriptor; private File f; private IEditorPart editor; - private Set getTM4EThreads() { - Set threads = Thread.getAllStackTraces().keySet(); - Set res = new HashSet<>(); - for (Thread thread : threads) { - if (thread.getClass().getName().contains("tm4e")) { - res.add(thread); - } - } - return res; + @BeforeEach + public void checkHasGenericEditor() { + editorDescriptor = PlatformUI.getWorkbench().getEditorRegistry() + .findEditor("org.eclipse.ui.genericeditor.GenericEditor"); + assertNotNull(editorDescriptor); } @BeforeEach - public void checkHasGenericEditor() { - editorDescriptor = PlatformUI.getWorkbench().getEditorRegistry().findEditor("org.eclipse.ui.genericeditor.GenericEditor"); - assumeTrue(editorDescriptor!=null); - assertTrue(getTM4EThreads().isEmpty(), "TM4E threads still running"); + public void checkNoTM4EThreadsRunning() throws InterruptedException { + var tm4eThreads = Thread.getAllStackTraces(); + tm4eThreads.entrySet().removeIf(e -> !e.getKey().getClass().getName().startsWith("org.eclipse.tm4e")); + + if (!tm4eThreads.isEmpty()) { + Thread.sleep(5_000); // give threads time to finish + } + + tm4eThreads = Thread.getAllStackTraces(); + tm4eThreads.entrySet().removeIf(e -> !e.getKey().getClass().getName().startsWith("org.eclipse.tm4e")); + + if (!tm4eThreads.isEmpty()) { + // print the stacktrace of one of the hung threads + final var tm4eThread = tm4eThreads.entrySet().iterator().next(); + final var ex = new IllegalStateException("Thread " + tm4eThread.getKey() + " is still busy"); + ex.setStackTrace(tm4eThread.getValue()); + ex.printStackTrace(System.out); + + fail("TM4E threads still running:\n" + tm4eThreads.keySet().stream() + .map(t -> " - " + t + " " + t.getClass().getName()).collect(Collectors.joining("\n"))); + } } @AfterEach @@ -77,15 +87,15 @@ public void tearDown() { } @Test - public void testTMHighlightInGenericEditor() throws IOException, PartInitException { + void testTMHighlightInGenericEditor() throws IOException, PartInitException { f = File.createTempFile("test" + System.currentTimeMillis(), ".ts"); - FileOutputStream fileOutputStream = new FileOutputStream(f); - fileOutputStream.write("let a = '';\nlet b = 10;\nlet c = true;".getBytes()); - fileOutputStream.close(); + try (FileOutputStream fileOutputStream = new FileOutputStream(f)) { + fileOutputStream.write("let a = '';\nlet b = 10;\nlet c = true;".getBytes()); + } f.deleteOnExit(); editor = IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), f.toURI(), editorDescriptor.getId(), true); - StyledText text = (StyledText)editor.getAdapter(Control.class); + StyledText text = (StyledText) editor.getAdapter(Control.class); assertTrue(new DisplayHelper() { @Override protected boolean condition() { @@ -95,15 +105,15 @@ protected boolean condition() { } @Test - public void testTMHighlightInGenericEditorEdit() throws IOException, PartInitException { + void testTMHighlightInGenericEditorEdit() throws IOException, PartInitException { f = File.createTempFile("test" + System.currentTimeMillis(), ".ts"); - FileOutputStream fileOutputStream = new FileOutputStream(f); - fileOutputStream.write("let a = '';".getBytes()); - fileOutputStream.close(); + try (FileOutputStream fileOutputStream = new FileOutputStream(f)) { + fileOutputStream.write("let a = '';".getBytes()); + } f.deleteOnExit(); editor = IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), f.toURI(), editorDescriptor.getId(), true); - StyledText text = (StyledText)editor.getAdapter(Control.class); + StyledText text = (StyledText) editor.getAdapter(Control.class); assertTrue(new DisplayHelper() { @Override protected boolean condition() { @@ -113,18 +123,17 @@ protected boolean condition() { int initialNumberOfRanges = text.getStyleRanges().length; text.setText("let a = '';\nlet b = 10;\nlet c = true;"); assertTrue(new DisplayHelper() { - @Override protected boolean condition() { + @Override + protected boolean condition() { return text.getStyleRanges().length > initialNumberOfRanges + 3; } }.waitForCondition(text.getDisplay(), 300000), "More styles should have been added"); } @Test - public void testReconcilierStartsAndDisposeThread() throws Exception { + void testReconcilierStartsAndDisposeThread() throws Exception { testTMHighlightInGenericEditor(); editor.getEditorSite().getPage().closeEditor(editor, false); - Thread.sleep(500); // give time to dispose - assertEquals(Collections.emptySet(), getTM4EThreads()); + checkNoTM4EThreadsRunning(); } - } diff --git a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/model/DocumentTMModelTest.java b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/model/DocumentTMModelTest.java similarity index 91% rename from org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/model/DocumentTMModelTest.java rename to org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/model/DocumentTMModelTest.java index e8d9e34b1..6a3c01c6e 100644 --- a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/model/DocumentTMModelTest.java +++ b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/model/DocumentTMModelTest.java @@ -15,10 +15,10 @@ import org.eclipse.tm4e.core.registry.Registry; import org.junit.jupiter.api.Test; -public class DocumentTMModelTest { +class DocumentTMModelTest { @Test - public void testMultiLineChange() throws Exception { + void testMultiLineChange() throws Exception { Document document = new Document(); TMDocumentModel model = new TMDocumentModel(document); try { diff --git a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/text/Command.java b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/text/Command.java similarity index 90% rename from org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/text/Command.java rename to org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/text/Command.java index bd33112df..434730d62 100644 --- a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/text/Command.java +++ b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/text/Command.java @@ -1,73 +1,73 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.text; - -import org.eclipse.tm4e.ui.text.ICommand; - -public abstract class Command implements ICommand { - - private final String name; - private String styleRanges; - private boolean done; - - public Command(String name) { - this.name = name; - this.done = false; - } - - @Override - public String getName() { - return name; - } - - public void setStyleRanges(String styleRanges) { - this.styleRanges = styleRanges; - } - - @Override - public String getStyleRanges() { - return styleRanges; - } - - public void execute() { - if (!done) { - doExecute(); - done = true; - } - } - - protected abstract void doExecute(); - - protected abstract Integer getLineTo(); - - public static String toText(String text) { - StringBuilder newText = new StringBuilder(); - for (int i = 0; i < text.length(); i++) { - char c = text.charAt(i); - switch (c) { - case '\n': - newText.append("\\n"); - break; - case '\r': - newText.append("\\r"); - break; - case '"': - newText.append("\\\""); - break; - default: - newText.append(c); - } - } - return newText.toString(); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.text; + +import org.eclipse.tm4e.ui.text.ICommand; + +public abstract class Command implements ICommand { + + private final String name; + private String styleRanges; + private boolean done; + + protected Command(String name) { + this.name = name; + this.done = false; + } + + @Override + public String getName() { + return name; + } + + public void setStyleRanges(String styleRanges) { + this.styleRanges = styleRanges; + } + + @Override + public String getStyleRanges() { + return styleRanges; + } + + public void execute() { + if (!done) { + doExecute(); + done = true; + } + } + + protected abstract void doExecute(); + + protected abstract Integer getLineTo(); + + public static String toText(String text) { + final StringBuilder newText = new StringBuilder(); + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + switch (c) { + case '\n': + newText.append("\\n"); + break; + case '\r': + newText.append("\\r"); + break; + case '"': + newText.append("\\\""); + break; + default: + newText.append(c); + } + } + return newText.toString(); + } + +} diff --git a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/text/DocumentReplaceCommand.java b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/text/DocumentReplaceCommand.java similarity index 96% rename from org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/text/DocumentReplaceCommand.java rename to org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/text/DocumentReplaceCommand.java index da9286d83..bcf7c610d 100644 --- a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/text/DocumentReplaceCommand.java +++ b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/text/DocumentReplaceCommand.java @@ -1,54 +1,54 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.text; - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.Document; - -public class DocumentReplaceCommand extends Command { - - private final int pos; - private final int length; - private final String text; - private final Document document; - - public DocumentReplaceCommand(int pos, int length, String text, Document document) { - super(getName(pos, length, text)); - this.pos = pos; - this.length = length; - this.text = text; - this.document = document; - } - - public static String getName(int pos, int length, String text) { - return "document.replace(" + pos + ", " + length + ", \"" + toText(text) + "\");"; - } - - @Override - protected void doExecute() { - try { - document.replace(pos, length, text); - } catch (BadLocationException e) { - e.printStackTrace(); - } - } - - @Override - protected Integer getLineTo() { - try { - return document.getLineOfOffset(pos + length); - } catch (BadLocationException e) { - return null; - } - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.text; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; + +public class DocumentReplaceCommand extends Command { + + private final int pos; + private final int length; + private final String text; + private final Document document; + + public DocumentReplaceCommand(int pos, int length, String text, Document document) { + super(getName(pos, length, text)); + this.pos = pos; + this.length = length; + this.text = text; + this.document = document; + } + + public static String getName(int pos, int length, String text) { + return "document.replace(" + pos + ", " + length + ", \"" + toText(text) + "\");"; + } + + @Override + protected void doExecute() { + try { + document.replace(pos, length, text); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + @Override + protected Integer getLineTo() { + try { + return document.getLineOfOffset(pos + length); + } catch (BadLocationException e) { + return null; + } + } + +} diff --git a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/text/DocumentSetCommand.java b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/text/DocumentSetCommand.java similarity index 96% rename from org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/text/DocumentSetCommand.java rename to org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/text/DocumentSetCommand.java index bd789b8d4..90f1c1413 100644 --- a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/text/DocumentSetCommand.java +++ b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/text/DocumentSetCommand.java @@ -1,41 +1,41 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.text; - -import org.eclipse.jface.text.Document; - -public class DocumentSetCommand extends Command { - - private final String text; - private final Document document; - - public DocumentSetCommand(String text, Document document) { - super(getName(text)); - this.text = text; - this.document = document; - } - - public static String getName(String text) { - return "document.set(\"" + toText(text) + "\");"; - } - - @Override - protected void doExecute() { - document.set(text); - } - - @Override - protected Integer getLineTo() { - int numberOfLines =document.getNumberOfLines(); - return numberOfLines > 0 ? numberOfLines - 1 : null; - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.text; + +import org.eclipse.jface.text.Document; + +public class DocumentSetCommand extends Command { + + private final String text; + private final Document document; + + public DocumentSetCommand(String text, Document document) { + super(getName(text)); + this.text = text; + this.document = document; + } + + public static String getName(String text) { + return "document.set(\"" + toText(text) + "\");"; + } + + @Override + protected void doExecute() { + document.set(text); + } + + @Override + protected Integer getLineTo() { + int numberOfLines =document.getNumberOfLines(); + return numberOfLines > 0 ? numberOfLines - 1 : null; + } +} diff --git a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/text/StyleRangesCollector.java b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/text/StyleRangesCollector.java similarity index 92% rename from org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/text/StyleRangesCollector.java rename to org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/text/StyleRangesCollector.java index f343ee66d..692539154 100644 --- a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/text/StyleRangesCollector.java +++ b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/text/StyleRangesCollector.java @@ -1,116 +1,115 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.text; - -import java.util.Arrays; -import java.util.Iterator; - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.ITextViewer; -import org.eclipse.jface.text.TextPresentation; -import org.eclipse.swt.custom.StyleRange; -import org.eclipse.tm4e.ui.text.ITMPresentationReconcilerListener; - -public class StyleRangesCollector implements ITMPresentationReconcilerListener { - - private IDocument document; - private Command command; - private Integer waitForToLineNumber; - private boolean isFinished; - - private StringBuilder currentRanges; - - private Object lock = new Object(); - - public StyleRangesCollector() { - - } - - @Override - public void install(ITextViewer viewer, IDocument document) { - this.document = document; - } - - @Override - public void uninstall() { - this.document = null; - } - - @Override - public void colorize(TextPresentation presentation, Throwable error) { - add(presentation); - if (waitForToLineNumber != null) { - int offset = presentation.getExtent().getOffset() + presentation.getExtent().getLength(); - try { - if (waitForToLineNumber != document.getLineOfOffset(offset)) { - return; - } else { - waitForToLineNumber = null; - } - } catch (BadLocationException e) { - e.printStackTrace(); - } - } - ((Command) command).setStyleRanges("[" + currentRanges.toString() + "]"); - synchronized (lock) { - lock.notifyAll(); - } - } - - private String add(TextPresentation presentation) { - Iterator ranges = presentation.getAllStyleRangeIterator(); - while(ranges.hasNext()) { - if (currentRanges.length() > 0) { - currentRanges.append(", "); - } - currentRanges.append(ranges.next()); - } - return null; - } - - public static String toString(StyleRange[] ranges) { - return Arrays.asList(ranges).toString(); - } - - public void executeCommand(Command command) { - setCommand(command); - if (command.getStyleRanges() == null) { - synchronized (lock) { - try { - wait(command); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } - - public void wait(Command command) throws InterruptedException { - lock.wait(); - if (command.getStyleRanges() == null) { - wait(command); - } - } - - public void setCommand(Command command) { - this.currentRanges = new StringBuilder(); - this.command = command; - this.waitForToLineNumber = command.getLineTo(); - command.execute(); - } - - public boolean isFinished() { - return isFinished; - } - + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.text; + +import java.util.Arrays; +import java.util.Iterator; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.TextPresentation; +import org.eclipse.swt.custom.StyleRange; +import org.eclipse.tm4e.ui.text.ITMPresentationReconcilerListener; + +public class StyleRangesCollector implements ITMPresentationReconcilerListener { + + private IDocument document; + private Command command; + private Integer waitForToLineNumber; + private boolean isFinished; + + private StringBuilder currentRanges; + + private Object lock = new Object(); + + public StyleRangesCollector() { + + } + + @Override + public void install(ITextViewer viewer, IDocument document) { + this.document = document; + } + + @Override + public void uninstall() { + this.document = null; + } + + @Override + public void colorize(TextPresentation presentation, Throwable error) { + add(presentation); + if (waitForToLineNumber != null) { + int offset = presentation.getExtent().getOffset() + presentation.getExtent().getLength(); + try { + if (waitForToLineNumber != document.getLineOfOffset(offset)) { + return; + } + waitForToLineNumber = null; + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + command.setStyleRanges("[" + currentRanges.toString() + "]"); + synchronized (lock) { + lock.notifyAll(); + } + } + + private String add(TextPresentation presentation) { + Iterator ranges = presentation.getAllStyleRangeIterator(); + while(ranges.hasNext()) { + if (currentRanges.length() > 0) { + currentRanges.append(", "); + } + currentRanges.append(ranges.next()); + } + return null; + } + + public static String toString(StyleRange[] ranges) { + return Arrays.asList(ranges).toString(); + } + + public void executeCommand(Command command) { + setCommand(command); + if (command.getStyleRanges() == null) { + synchronized (lock) { + try { + wait(command); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + public void wait(Command command) throws InterruptedException { + lock.wait(); + if (command.getStyleRanges() == null) { + wait(command); + } + } + + public void setCommand(Command command) { + this.currentRanges = new StringBuilder(); + this.command = command; + this.waitForToLineNumber = command.getLineTo(); + command.execute(); + } + + public boolean isFinished() { + return isFinished; + } + } \ No newline at end of file diff --git a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/text/TextViewerInvalidateTextPresentationCommand.java b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/text/TextViewerInvalidateTextPresentationCommand.java similarity index 96% rename from org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/text/TextViewerInvalidateTextPresentationCommand.java rename to org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/text/TextViewerInvalidateTextPresentationCommand.java index a6b1ff3ae..de03fbccb 100644 --- a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/text/TextViewerInvalidateTextPresentationCommand.java +++ b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/internal/text/TextViewerInvalidateTextPresentationCommand.java @@ -1,54 +1,54 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.text; - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.TextViewer; - -public class TextViewerInvalidateTextPresentationCommand extends Command { - - private final int offset; - private final int length; - private final TextViewer viewer; - - public TextViewerInvalidateTextPresentationCommand(int offset, int length, TextViewer viewer) { - super(getName(offset, length)); - this.offset = offset; - this.length = length; - this.viewer = viewer; - } - - public static String getName(int offset, int length) { - return "viewer.invalidateTextPresentation(" + offset + ", " + length + ");"; - } - - @Override - protected void doExecute() { - viewer.getTextWidget().getDisplay().syncExec(new Runnable() { - - @Override - public void run() { - viewer.invalidateTextPresentation(offset, length); - } - }); - } - - @Override - protected Integer getLineTo() { - try { - return viewer.getDocument().getLineOfOffset(offset + length); - } catch (BadLocationException e) { - return null; - } - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.text; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.TextViewer; + +public class TextViewerInvalidateTextPresentationCommand extends Command { + + private final int offset; + private final int length; + private final TextViewer viewer; + + public TextViewerInvalidateTextPresentationCommand(int offset, int length, TextViewer viewer) { + super(getName(offset, length)); + this.offset = offset; + this.length = length; + this.viewer = viewer; + } + + public static String getName(int offset, int length) { + return "viewer.invalidateTextPresentation(" + offset + ", " + length + ");"; + } + + @Override + protected void doExecute() { + viewer.getTextWidget().getDisplay().syncExec(new Runnable() { + + @Override + public void run() { + viewer.invalidateTextPresentation(offset, length); + } + }); + } + + @Override + protected Integer getLineTo() { + try { + return viewer.getDocument().getLineOfOffset(offset + length); + } catch (BadLocationException e) { + return null; + } + } + +} diff --git a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/text/ICommand.java b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/text/ICommand.java similarity index 98% rename from org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/text/ICommand.java rename to org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/text/ICommand.java index 38e617e91..6da479436 100644 --- a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/text/ICommand.java +++ b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/text/ICommand.java @@ -9,12 +9,12 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.ui.text; - -public interface ICommand { - - String getName(); - - String getStyleRanges(); - -} +package org.eclipse.tm4e.ui.text; + +public interface ICommand { + + String getName(); + + String getStyleRanges(); + +} diff --git a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/text/TMEditor.java b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/text/TMEditor.java similarity index 91% rename from org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/text/TMEditor.java rename to org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/text/TMEditor.java index 07efeecf8..d505c5296 100644 --- a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/text/TMEditor.java +++ b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/text/TMEditor.java @@ -9,12 +9,11 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.ui.text; - +package org.eclipse.tm4e.ui.text; + import java.util.ArrayList; import java.util.List; -import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.TextViewer; import org.eclipse.swt.SWT; @@ -26,79 +25,79 @@ import org.eclipse.tm4e.ui.internal.text.DocumentSetCommand; import org.eclipse.tm4e.ui.internal.text.StyleRangesCollector; import org.eclipse.tm4e.ui.internal.text.TextViewerInvalidateTextPresentationCommand; -import org.eclipse.tm4e.ui.themes.ITokenProvider; - -public class TMEditor { - - private final TextViewer viewer; - private final Document document; - private final Shell shell; - private StyleRangesCollector collector; - - private final List commands; - private TMPresentationReconciler reconciler; - - public TMEditor(IGrammar grammar, ITokenProvider tokenProvider, String text) { - shell = new Shell(); - viewer = new TextViewer(shell, SWT.NONE); - document = new Document(); - viewer.setDocument(document); - commands = new ArrayList<>(); - collector = new StyleRangesCollector(); - - setAndExecute(text); - - reconciler = new TMPresentationReconciler(); - reconciler.addTMPresentationReconcilerListener(collector); - reconciler.setGrammar(grammar); - reconciler.setTheme(tokenProvider); - reconciler.install(viewer); - - } - - public void set(String text) { - commands.add(new DocumentSetCommand(text, document)); - } - - private void setAndExecute(String text) { - Command command = new DocumentSetCommand(text, document); - commands.add(command); - collector.setCommand(command); - } - - public void replace(int pos, int length, String text) throws BadLocationException { - commands.add(new DocumentReplaceCommand(pos, length, text, document)); - } - - /** - * Invalidates the given range of the text presentation. - * - * @param offset - * the offset of the range to be invalidated - * @param length - * the length of the range to be invalidated - * - */ - public void invalidateTextPresentation(int offset, int length) { - commands.add(new TextViewerInvalidateTextPresentationCommand(offset, length, viewer)); - } - - public List execute() { - new Thread(() -> { - for (ICommand command : commands) { - collector.executeCommand((Command) command); - } - shell.getDisplay().syncExec(() -> shell.dispose()); - }).start(); - - Display display = shell.getDisplay(); - while (!shell.isDisposed()) { - if (!display.readAndDispatch()) { - display.sleep(); - } - } - reconciler.uninstall(); - return commands; - } - -} +import org.eclipse.tm4e.ui.themes.ITokenProvider; + +public class TMEditor { + + private final TextViewer viewer; + private final Document document; + private final Shell shell; + private StyleRangesCollector collector; + + private final List commands; + private TMPresentationReconciler reconciler; + + public TMEditor(IGrammar grammar, ITokenProvider tokenProvider, String text) { + shell = new Shell(); + viewer = new TextViewer(shell, SWT.NONE); + document = new Document(); + viewer.setDocument(document); + commands = new ArrayList<>(); + collector = new StyleRangesCollector(); + + setAndExecute(text); + + reconciler = new TMPresentationReconciler(); + reconciler.addTMPresentationReconcilerListener(collector); + reconciler.setGrammar(grammar); + reconciler.setTheme(tokenProvider); + reconciler.install(viewer); + + } + + public void set(String text) { + commands.add(new DocumentSetCommand(text, document)); + } + + private void setAndExecute(String text) { + Command command = new DocumentSetCommand(text, document); + commands.add(command); + collector.setCommand(command); + } + + public void replace(int pos, int length, String text) { + commands.add(new DocumentReplaceCommand(pos, length, text, document)); + } + + /** + * Invalidates the given range of the text presentation. + * + * @param offset + * the offset of the range to be invalidated + * @param length + * the length of the range to be invalidated + * + */ + public void invalidateTextPresentation(int offset, int length) { + commands.add(new TextViewerInvalidateTextPresentationCommand(offset, length, viewer)); + } + + public List execute() { + new Thread(() -> { + for (ICommand command : commands) { + collector.executeCommand((Command) command); + } + shell.getDisplay().syncExec(shell::dispose); + }).start(); + + Display display = shell.getDisplay(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + reconciler.uninstall(); + return commands; + } + +} diff --git a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/text/typescript/TMPresentationReconcilerTypeScriptTest.java b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/text/typescript/TMPresentationReconcilerTypeScriptTest.java similarity index 94% rename from org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/text/typescript/TMPresentationReconcilerTypeScriptTest.java rename to org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/text/typescript/TMPresentationReconcilerTypeScriptTest.java index a2ed1c7db..fe7827862 100644 --- a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/text/typescript/TMPresentationReconcilerTypeScriptTest.java +++ b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/text/typescript/TMPresentationReconcilerTypeScriptTest.java @@ -9,8 +9,8 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.ui.text.typescript; - +package org.eclipse.tm4e.ui.text.typescript; + import static org.junit.jupiter.api.Assertions.*; import java.util.List; @@ -23,328 +23,328 @@ import org.eclipse.tm4e.ui.themes.css.CSSTokenProvider; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; - -public class TMPresentationReconcilerTypeScriptTest { - - @Disabled ("Remove this annotation when org.eclipse.swt.SWTError: No more handles [gtk_init_check() failed] will be fixed") - @Test - public void colorizeTypescript() throws Exception { - - TMEditor editor = new TMEditor(getGrammar(), getTokenProvider(), "let a = '';\nlet b = 10;\nlet c = true;"); - List commands = editor.execute(); - - assertEquals(1, commands.size()); - ICommand command = commands.get(0); - - assertEquals( - "[" - + "StyleRange {0, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {3, 1, fontStyle=normal}, " - + "StyleRange {4, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {5, 1, fontStyle=normal}, " - + "StyleRange {6, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {7, 1, fontStyle=normal}, " - + "StyleRange {8, 2, fontStyle=normal, foreground=Color {42, 161, 152, 255}}, " - + "StyleRange {10, 2, fontStyle=normal}, " - + "StyleRange {12, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {15, 1, fontStyle=normal}, " - + "StyleRange {16, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {17, 1, fontStyle=normal}, " - + "StyleRange {18, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {19, 1, fontStyle=normal}, " - + "StyleRange {20, 2, fontStyle=normal, foreground=Color {211, 54, 130, 255}}, " - + "StyleRange {22, 2, fontStyle=normal}, " - + "StyleRange {24, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {27, 1, fontStyle=normal}, " - + "StyleRange {28, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {29, 1, fontStyle=normal}, " - + "StyleRange {30, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {31, 1, fontStyle=normal}, " - + "StyleRange {32, 4, fontStyle=normal, foreground=Color {181, 137, 0, 255}}, " - + "StyleRange {36, 1, fontStyle=normal}" - + "]", - command.getStyleRanges()); - } - - @Disabled ("Remove this annotation when org.eclipse.swt.SWTError: No more handles [gtk_init_check() failed] will be fixed") - @Test - public void colorizeTypescriptWithInvalidate1() throws Exception { - - TMEditor editor = new TMEditor(getGrammar(), getTokenProvider(), "let a = '';\nlet b = 10;\nlet c = true;"); - editor.invalidateTextPresentation(0, 3); - List commands = editor.execute(); - - // document.set("let a = '';\nlet b = 10;\nlet c = true;"); - ICommand command0 = commands.get(0); - assertEquals( - "[" - + "StyleRange {0, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {3, 1, fontStyle=normal}, " - + "StyleRange {4, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {5, 1, fontStyle=normal}, " - + "StyleRange {6, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {7, 1, fontStyle=normal}, " - + "StyleRange {8, 2, fontStyle=normal, foreground=Color {42, 161, 152, 255}}, " - + "StyleRange {10, 2, fontStyle=normal}, " - + "StyleRange {12, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {15, 1, fontStyle=normal}, " - + "StyleRange {16, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {17, 1, fontStyle=normal}, " - + "StyleRange {18, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {19, 1, fontStyle=normal}, " - + "StyleRange {20, 2, fontStyle=normal, foreground=Color {211, 54, 130, 255}}, " - + "StyleRange {22, 2, fontStyle=normal}, " - + "StyleRange {24, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {27, 1, fontStyle=normal}, " - + "StyleRange {28, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {29, 1, fontStyle=normal}, " - + "StyleRange {30, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {31, 1, fontStyle=normal}, " - + "StyleRange {32, 4, fontStyle=normal, foreground=Color {181, 137, 0, 255}}, " - + "StyleRange {36, 1, fontStyle=normal}" - + "]", - command0.getStyleRanges()); - - // viewer.invalidateTextPresentation(0, 3); - ICommand command1 = commands.get(1); - assertEquals( - "[" - + "StyleRange {0, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}" - + "]", - command1.getStyleRanges()); - - } - - @Disabled - @Test - public void colorizeTypescriptWithInvalidate2() throws Exception { - - TMEditor editor = new TMEditor(getGrammar(), getTokenProvider(), "let a = '';\nlet b = 10;\nlet c = true;"); - editor.invalidateTextPresentation(0, 2); - List commands = editor.execute(); - - // document.set("let a = '';\nlet b = 10;\nlet c = true;"); - ICommand command0 = commands.get(0); - assertEquals( - "[" - + "StyleRange {0, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {3, 1, fontStyle=normal}, " - + "StyleRange {4, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {5, 1, fontStyle=normal}, " - + "StyleRange {6, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {7, 1, fontStyle=normal}, " - + "StyleRange {8, 2, fontStyle=normal, foreground=Color {42, 161, 152, 255}}, " - + "StyleRange {10, 2, fontStyle=normal}, " - + "StyleRange {12, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {15, 1, fontStyle=normal}, " - + "StyleRange {16, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {17, 1, fontStyle=normal}, " - + "StyleRange {18, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {19, 1, fontStyle=normal}, " - + "StyleRange {20, 2, fontStyle=normal, foreground=Color {211, 54, 130, 255}}, " - + "StyleRange {22, 2, fontStyle=normal}, " - + "StyleRange {24, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {27, 1, fontStyle=normal}, " - + "StyleRange {28, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {29, 1, fontStyle=normal}, " - + "StyleRange {30, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {31, 1, fontStyle=normal}, " - + "StyleRange {32, 4, fontStyle=normal, foreground=Color {181, 137, 0, 255}}, " - + "StyleRange {36, 1, fontStyle=normal}" - + "]", - command0.getStyleRanges()); - - // viewer.invalidateTextPresentation(0, 2); - ICommand command1 = commands.get(1); - assertEquals( - "[" - + "StyleRange {0, 2, fontStyle=bold, foreground=Color {7, 54, 66, 255}}" - + "]", - command1.getStyleRanges()); - - } - - @Disabled ("Remove this annotation when org.eclipse.swt.SWTError: No more handles [gtk_init_check() failed] will be fixed") - @Test - public void colorizeTypescriptWithInvalidate3() throws Exception { - - TMEditor editor = new TMEditor(getGrammar(), getTokenProvider(), "let a = '';\nlet b = 10;\nlet c = true;"); - editor.invalidateTextPresentation(1, 2); - List commands = editor.execute(); - - // document.set("let a = '';\nlet b = 10;\nlet c = true;"); - ICommand command0 = commands.get(0); - assertEquals( - "[" - + "StyleRange {0, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {3, 1, fontStyle=normal}, " - + "StyleRange {4, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {5, 1, fontStyle=normal}, " - + "StyleRange {6, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {7, 1, fontStyle=normal}, " - + "StyleRange {8, 2, fontStyle=normal, foreground=Color {42, 161, 152, 255}}, " - + "StyleRange {10, 2, fontStyle=normal}, " - + "StyleRange {12, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {15, 1, fontStyle=normal}, " - + "StyleRange {16, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {17, 1, fontStyle=normal}, " - + "StyleRange {18, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {19, 1, fontStyle=normal}, " - + "StyleRange {20, 2, fontStyle=normal, foreground=Color {211, 54, 130, 255}}, " - + "StyleRange {22, 2, fontStyle=normal}, " - + "StyleRange {24, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {27, 1, fontStyle=normal}, " - + "StyleRange {28, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {29, 1, fontStyle=normal}, " - + "StyleRange {30, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {31, 1, fontStyle=normal}, " - + "StyleRange {32, 4, fontStyle=normal, foreground=Color {181, 137, 0, 255}}, " - + "StyleRange {36, 1, fontStyle=normal}" - + "]", - command0.getStyleRanges()); - - // viewer.invalidateTextPresentation(1, 2); - ICommand command1 = commands.get(1); - assertEquals( - "[" - + "StyleRange {1, 2, fontStyle=bold, foreground=Color {7, 54, 66, 255}}" - + "]", - command1.getStyleRanges()); - - } - - @Disabled - @Test - public void colorizeTypescriptWithInvalidate4() throws Exception { - - TMEditor editor = new TMEditor(getGrammar(), getTokenProvider(), "let a = '';\nlet b = 10;\nlet c = true;"); - editor.invalidateTextPresentation(1, 1); - List commands = editor.execute(); - - // document.set("let a = '';\nlet b = 10;\nlet c = true;"); - ICommand command0 = commands.get(0); - assertEquals( - "[" - + "StyleRange {0, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {3, 1, fontStyle=normal}, " - + "StyleRange {4, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {5, 1, fontStyle=normal}, " - + "StyleRange {6, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {7, 1, fontStyle=normal}, " - + "StyleRange {8, 2, fontStyle=normal, foreground=Color {42, 161, 152, 255}}, " - + "StyleRange {10, 2, fontStyle=normal}, " - + "StyleRange {12, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {15, 1, fontStyle=normal}, " - + "StyleRange {16, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {17, 1, fontStyle=normal}, " - + "StyleRange {18, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {19, 1, fontStyle=normal}, " - + "StyleRange {20, 2, fontStyle=normal, foreground=Color {211, 54, 130, 255}}, " - + "StyleRange {22, 2, fontStyle=normal}, " - + "StyleRange {24, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {27, 1, fontStyle=normal}, " - + "StyleRange {28, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {29, 1, fontStyle=normal}, " - + "StyleRange {30, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {31, 1, fontStyle=normal}, " - + "StyleRange {32, 4, fontStyle=normal, foreground=Color {181, 137, 0, 255}}, " - + "StyleRange {36, 1, fontStyle=normal}" - + "]", - command0.getStyleRanges()); - - // viewer.invalidateTextPresentation(1, 1); - ICommand command1 = commands.get(1); - assertEquals( - "[" - + "StyleRange {1, 1, fontStyle=bold, foreground=Color {7, 54, 66, 255}}" - + "]", - command1.getStyleRanges()); - - } - - @Disabled - @Test - public void colorizeTypescriptWithInvalidate8() throws Exception { - - TMEditor editor = new TMEditor(getGrammar(), getTokenProvider(), "let a = '';\nlet b = 10;\nlet c = true;"); - editor.invalidateTextPresentation(1, 8); - List commands = editor.execute(); - - // document.set("let a = '';\nlet b = 10;\nlet c = true;"); - ICommand command0 = commands.get(0); - assertEquals( - "[" - + "StyleRange {0, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {3, 1, fontStyle=normal}, " - + "StyleRange {4, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {5, 1, fontStyle=normal}, " - + "StyleRange {6, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {7, 1, fontStyle=normal}, " - + "StyleRange {8, 2, fontStyle=normal, foreground=Color {42, 161, 152, 255}}, " - + "StyleRange {10, 2, fontStyle=normal}, " - + "StyleRange {12, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {15, 1, fontStyle=normal}, " - + "StyleRange {16, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {17, 1, fontStyle=normal}, " - + "StyleRange {18, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {19, 1, fontStyle=normal}, " - + "StyleRange {20, 2, fontStyle=normal, foreground=Color {211, 54, 130, 255}}, " - + "StyleRange {22, 2, fontStyle=normal}, " - + "StyleRange {24, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " - + "StyleRange {27, 1, fontStyle=normal}, " - + "StyleRange {28, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {29, 1, fontStyle=normal}, " - + "StyleRange {30, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " - + "StyleRange {31, 1, fontStyle=normal}, " - + "StyleRange {32, 4, fontStyle=normal, foreground=Color {181, 137, 0, 255}}, " - + "StyleRange {36, 1, fontStyle=normal}" - + "]", - command0.getStyleRanges()); - - // viewer.invalidateTextPresentation(1, 8); - ICommand command1 = commands.get(1); - assertEquals( - "[" - + "StyleRange {1, 2, fontStyle=bold, foreground=Color {7, 54, 66, 255}}" - + "]", - command1.getStyleRanges()); - - } - - @Disabled ("Remove this annotation when org.eclipse.swt.SWTError: No more handles [gtk_init_check() failed] will be fixed") - @Test - public void colorizeTypescriptWithInvalidateAndSeveralLines() throws Exception { - - TMEditor editor = new TMEditor(getGrammar(), getTokenProvider(), "a\r\n\r\nb"); - editor.invalidateTextPresentation(0, 6); - - List commands = editor.execute(); - - assertEquals(2, commands.size()); - - for (ICommand command : commands) { - assertEquals( - "[" - + "StyleRange {0, 3, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " - + "StyleRange {3, 2, fontStyle=normal}, " - + "StyleRange {5, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}" - + "]", - command.getStyleRanges()); - } - } - - private static ITokenProvider getTokenProvider() { - return new CSSTokenProvider(TMEditor.class.getResourceAsStream("Solarized-light.css")); - } - - public static IGrammar getGrammar() { - Registry registry = new Registry(); - try { - return registry.loadGrammarFromPathSync("TypeScript.tmLanguage.json", - TMPresentationReconcilerTypeScriptTest.class.getClassLoader().getResourceAsStream("/grammars/TypeScript.tmLanguage.json")); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } + +public class TMPresentationReconcilerTypeScriptTest { + + @Disabled ("Remove this annotation when org.eclipse.swt.SWTError: No more handles [gtk_init_check() failed] will be fixed") + @Test + void colorizeTypescript() throws Exception { + + TMEditor editor = new TMEditor(getGrammar(), getTokenProvider(), "let a = '';\nlet b = 10;\nlet c = true;"); + List commands = editor.execute(); + + assertEquals(1, commands.size()); + ICommand command = commands.get(0); + + assertEquals( + "[" + + "StyleRange {0, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {3, 1, fontStyle=normal}, " + + "StyleRange {4, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {5, 1, fontStyle=normal}, " + + "StyleRange {6, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {7, 1, fontStyle=normal}, " + + "StyleRange {8, 2, fontStyle=normal, foreground=Color {42, 161, 152, 255}}, " + + "StyleRange {10, 2, fontStyle=normal}, " + + "StyleRange {12, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {15, 1, fontStyle=normal}, " + + "StyleRange {16, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {17, 1, fontStyle=normal}, " + + "StyleRange {18, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {19, 1, fontStyle=normal}, " + + "StyleRange {20, 2, fontStyle=normal, foreground=Color {211, 54, 130, 255}}, " + + "StyleRange {22, 2, fontStyle=normal}, " + + "StyleRange {24, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {27, 1, fontStyle=normal}, " + + "StyleRange {28, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {29, 1, fontStyle=normal}, " + + "StyleRange {30, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {31, 1, fontStyle=normal}, " + + "StyleRange {32, 4, fontStyle=normal, foreground=Color {181, 137, 0, 255}}, " + + "StyleRange {36, 1, fontStyle=normal}" + + "]", + command.getStyleRanges()); + } + + @Disabled ("Remove this annotation when org.eclipse.swt.SWTError: No more handles [gtk_init_check() failed] will be fixed") + @Test + void colorizeTypescriptWithInvalidate1() throws Exception { + + TMEditor editor = new TMEditor(getGrammar(), getTokenProvider(), "let a = '';\nlet b = 10;\nlet c = true;"); + editor.invalidateTextPresentation(0, 3); + List commands = editor.execute(); + + // document.set("let a = '';\nlet b = 10;\nlet c = true;"); + ICommand command0 = commands.get(0); + assertEquals( + "[" + + "StyleRange {0, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {3, 1, fontStyle=normal}, " + + "StyleRange {4, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {5, 1, fontStyle=normal}, " + + "StyleRange {6, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {7, 1, fontStyle=normal}, " + + "StyleRange {8, 2, fontStyle=normal, foreground=Color {42, 161, 152, 255}}, " + + "StyleRange {10, 2, fontStyle=normal}, " + + "StyleRange {12, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {15, 1, fontStyle=normal}, " + + "StyleRange {16, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {17, 1, fontStyle=normal}, " + + "StyleRange {18, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {19, 1, fontStyle=normal}, " + + "StyleRange {20, 2, fontStyle=normal, foreground=Color {211, 54, 130, 255}}, " + + "StyleRange {22, 2, fontStyle=normal}, " + + "StyleRange {24, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {27, 1, fontStyle=normal}, " + + "StyleRange {28, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {29, 1, fontStyle=normal}, " + + "StyleRange {30, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {31, 1, fontStyle=normal}, " + + "StyleRange {32, 4, fontStyle=normal, foreground=Color {181, 137, 0, 255}}, " + + "StyleRange {36, 1, fontStyle=normal}" + + "]", + command0.getStyleRanges()); + + // viewer.invalidateTextPresentation(0, 3); + ICommand command1 = commands.get(1); + assertEquals( + "[" + + "StyleRange {0, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}" + + "]", + command1.getStyleRanges()); + + } + + @Disabled + @Test + void colorizeTypescriptWithInvalidate2() throws Exception { + + TMEditor editor = new TMEditor(getGrammar(), getTokenProvider(), "let a = '';\nlet b = 10;\nlet c = true;"); + editor.invalidateTextPresentation(0, 2); + List commands = editor.execute(); + + // document.set("let a = '';\nlet b = 10;\nlet c = true;"); + ICommand command0 = commands.get(0); + assertEquals( + "[" + + "StyleRange {0, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {3, 1, fontStyle=normal}, " + + "StyleRange {4, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {5, 1, fontStyle=normal}, " + + "StyleRange {6, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {7, 1, fontStyle=normal}, " + + "StyleRange {8, 2, fontStyle=normal, foreground=Color {42, 161, 152, 255}}, " + + "StyleRange {10, 2, fontStyle=normal}, " + + "StyleRange {12, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {15, 1, fontStyle=normal}, " + + "StyleRange {16, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {17, 1, fontStyle=normal}, " + + "StyleRange {18, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {19, 1, fontStyle=normal}, " + + "StyleRange {20, 2, fontStyle=normal, foreground=Color {211, 54, 130, 255}}, " + + "StyleRange {22, 2, fontStyle=normal}, " + + "StyleRange {24, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {27, 1, fontStyle=normal}, " + + "StyleRange {28, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {29, 1, fontStyle=normal}, " + + "StyleRange {30, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {31, 1, fontStyle=normal}, " + + "StyleRange {32, 4, fontStyle=normal, foreground=Color {181, 137, 0, 255}}, " + + "StyleRange {36, 1, fontStyle=normal}" + + "]", + command0.getStyleRanges()); + + // viewer.invalidateTextPresentation(0, 2); + ICommand command1 = commands.get(1); + assertEquals( + "[" + + "StyleRange {0, 2, fontStyle=bold, foreground=Color {7, 54, 66, 255}}" + + "]", + command1.getStyleRanges()); + + } + + @Disabled ("Remove this annotation when org.eclipse.swt.SWTError: No more handles [gtk_init_check() failed] will be fixed") + @Test + void colorizeTypescriptWithInvalidate3() throws Exception { + + TMEditor editor = new TMEditor(getGrammar(), getTokenProvider(), "let a = '';\nlet b = 10;\nlet c = true;"); + editor.invalidateTextPresentation(1, 2); + List commands = editor.execute(); + + // document.set("let a = '';\nlet b = 10;\nlet c = true;"); + ICommand command0 = commands.get(0); + assertEquals( + "[" + + "StyleRange {0, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {3, 1, fontStyle=normal}, " + + "StyleRange {4, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {5, 1, fontStyle=normal}, " + + "StyleRange {6, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {7, 1, fontStyle=normal}, " + + "StyleRange {8, 2, fontStyle=normal, foreground=Color {42, 161, 152, 255}}, " + + "StyleRange {10, 2, fontStyle=normal}, " + + "StyleRange {12, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {15, 1, fontStyle=normal}, " + + "StyleRange {16, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {17, 1, fontStyle=normal}, " + + "StyleRange {18, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {19, 1, fontStyle=normal}, " + + "StyleRange {20, 2, fontStyle=normal, foreground=Color {211, 54, 130, 255}}, " + + "StyleRange {22, 2, fontStyle=normal}, " + + "StyleRange {24, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {27, 1, fontStyle=normal}, " + + "StyleRange {28, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {29, 1, fontStyle=normal}, " + + "StyleRange {30, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {31, 1, fontStyle=normal}, " + + "StyleRange {32, 4, fontStyle=normal, foreground=Color {181, 137, 0, 255}}, " + + "StyleRange {36, 1, fontStyle=normal}" + + "]", + command0.getStyleRanges()); + + // viewer.invalidateTextPresentation(1, 2); + ICommand command1 = commands.get(1); + assertEquals( + "[" + + "StyleRange {1, 2, fontStyle=bold, foreground=Color {7, 54, 66, 255}}" + + "]", + command1.getStyleRanges()); + + } + + @Disabled + @Test + void colorizeTypescriptWithInvalidate4() throws Exception { + + TMEditor editor = new TMEditor(getGrammar(), getTokenProvider(), "let a = '';\nlet b = 10;\nlet c = true;"); + editor.invalidateTextPresentation(1, 1); + List commands = editor.execute(); + + // document.set("let a = '';\nlet b = 10;\nlet c = true;"); + ICommand command0 = commands.get(0); + assertEquals( + "[" + + "StyleRange {0, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {3, 1, fontStyle=normal}, " + + "StyleRange {4, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {5, 1, fontStyle=normal}, " + + "StyleRange {6, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {7, 1, fontStyle=normal}, " + + "StyleRange {8, 2, fontStyle=normal, foreground=Color {42, 161, 152, 255}}, " + + "StyleRange {10, 2, fontStyle=normal}, " + + "StyleRange {12, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {15, 1, fontStyle=normal}, " + + "StyleRange {16, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {17, 1, fontStyle=normal}, " + + "StyleRange {18, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {19, 1, fontStyle=normal}, " + + "StyleRange {20, 2, fontStyle=normal, foreground=Color {211, 54, 130, 255}}, " + + "StyleRange {22, 2, fontStyle=normal}, " + + "StyleRange {24, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {27, 1, fontStyle=normal}, " + + "StyleRange {28, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {29, 1, fontStyle=normal}, " + + "StyleRange {30, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {31, 1, fontStyle=normal}, " + + "StyleRange {32, 4, fontStyle=normal, foreground=Color {181, 137, 0, 255}}, " + + "StyleRange {36, 1, fontStyle=normal}" + + "]", + command0.getStyleRanges()); + + // viewer.invalidateTextPresentation(1, 1); + ICommand command1 = commands.get(1); + assertEquals( + "[" + + "StyleRange {1, 1, fontStyle=bold, foreground=Color {7, 54, 66, 255}}" + + "]", + command1.getStyleRanges()); + + } + + @Disabled + @Test + void colorizeTypescriptWithInvalidate8() throws Exception { + + TMEditor editor = new TMEditor(getGrammar(), getTokenProvider(), "let a = '';\nlet b = 10;\nlet c = true;"); + editor.invalidateTextPresentation(1, 8); + List commands = editor.execute(); + + // document.set("let a = '';\nlet b = 10;\nlet c = true;"); + ICommand command0 = commands.get(0); + assertEquals( + "[" + + "StyleRange {0, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {3, 1, fontStyle=normal}, " + + "StyleRange {4, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {5, 1, fontStyle=normal}, " + + "StyleRange {6, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {7, 1, fontStyle=normal}, " + + "StyleRange {8, 2, fontStyle=normal, foreground=Color {42, 161, 152, 255}}, " + + "StyleRange {10, 2, fontStyle=normal}, " + + "StyleRange {12, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {15, 1, fontStyle=normal}, " + + "StyleRange {16, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {17, 1, fontStyle=normal}, " + + "StyleRange {18, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {19, 1, fontStyle=normal}, " + + "StyleRange {20, 2, fontStyle=normal, foreground=Color {211, 54, 130, 255}}, " + + "StyleRange {22, 2, fontStyle=normal}, " + + "StyleRange {24, 3, fontStyle=bold, foreground=Color {7, 54, 66, 255}}, " + + "StyleRange {27, 1, fontStyle=normal}, " + + "StyleRange {28, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {29, 1, fontStyle=normal}, " + + "StyleRange {30, 1, fontStyle=normal, foreground=Color {133, 153, 0, 255}}, " + + "StyleRange {31, 1, fontStyle=normal}, " + + "StyleRange {32, 4, fontStyle=normal, foreground=Color {181, 137, 0, 255}}, " + + "StyleRange {36, 1, fontStyle=normal}" + + "]", + command0.getStyleRanges()); + + // viewer.invalidateTextPresentation(1, 8); + ICommand command1 = commands.get(1); + assertEquals( + "[" + + "StyleRange {1, 2, fontStyle=bold, foreground=Color {7, 54, 66, 255}}" + + "]", + command1.getStyleRanges()); + + } + + @Disabled ("Remove this annotation when org.eclipse.swt.SWTError: No more handles [gtk_init_check() failed] will be fixed") + @Test + void colorizeTypescriptWithInvalidateAndSeveralLines() throws Exception { + + TMEditor editor = new TMEditor(getGrammar(), getTokenProvider(), "a\r\n\r\nb"); + editor.invalidateTextPresentation(0, 6); + + List commands = editor.execute(); + + assertEquals(2, commands.size()); + + for (ICommand command : commands) { + assertEquals( + "[" + + "StyleRange {0, 3, fontStyle=normal, foreground=Color {38, 139, 210, 255}}, " + + "StyleRange {3, 2, fontStyle=normal}, " + + "StyleRange {5, 1, fontStyle=normal, foreground=Color {38, 139, 210, 255}}" + + "]", + command.getStyleRanges()); + } + } + + private static ITokenProvider getTokenProvider() { + return new CSSTokenProvider(TMEditor.class.getResourceAsStream("Solarized-light.css")); + } + + public static IGrammar getGrammar() { + Registry registry = new Registry(); + try { + return registry.loadGrammarFromPathSync("TypeScript.tmLanguage.json", + TMPresentationReconcilerTypeScriptTest.class.getClassLoader().getResourceAsStream("/grammars/TypeScript.tmLanguage.json")); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } } \ No newline at end of file diff --git a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/themes/MockThemeManager.java b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/themes/MockThemeManager.java similarity index 98% rename from org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/themes/MockThemeManager.java rename to org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/themes/MockThemeManager.java index 796737abb..d0e356a66 100644 --- a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/themes/MockThemeManager.java +++ b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/themes/MockThemeManager.java @@ -9,16 +9,16 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.ui.themes; - -import org.eclipse.tm4e.ui.internal.themes.AbstractThemeManager; -import org.osgi.service.prefs.BackingStoreException; - -public class MockThemeManager extends AbstractThemeManager { - - @Override - public void save() throws BackingStoreException { - - } - -} +package org.eclipse.tm4e.ui.themes; + +import org.eclipse.tm4e.ui.internal.themes.AbstractThemeManager; +import org.osgi.service.prefs.BackingStoreException; + +public class MockThemeManager extends AbstractThemeManager { + + @Override + public void save() throws BackingStoreException { + + } + +} diff --git a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/themes/TMEditorColorTest.java b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/themes/TMEditorColorTest.java similarity index 93% rename from org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/themes/TMEditorColorTest.java rename to org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/themes/TMEditorColorTest.java index e29454ee9..77b00fb93 100644 --- a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/themes/TMEditorColorTest.java +++ b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/themes/TMEditorColorTest.java @@ -35,7 +35,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class TMEditorColorTest implements ThemeIdConstants { +class TMEditorColorTest implements ThemeIdConstants { private static final String EDITOR_CURRENTLINE_HIGHLIGHT = "currentLineColor"; @@ -65,7 +65,7 @@ public void tearDown() { } @Test - public void systemDefaultEditorColorTest() throws IOException, PartInitException { + void systemDefaultEditorColorTest() throws IOException, PartInitException { f = File.createTempFile("test" + System.currentTimeMillis(), ".ts"); editor = IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), f.toURI(), @@ -75,7 +75,7 @@ public void systemDefaultEditorColorTest() throws IOException, PartInitException String themeId = manager.getDefaultTheme().getId(); ITheme theme = manager.getThemeById(themeId); - assertEquals(themeId, SolarizedLight, "Default light theme isn't set"); + assertEquals(SolarizedLight, themeId, "Default light theme isn't set"); assertEquals(theme.getEditorBackground(), styledText.getBackground(), "Background colors isn't equals"); assertEquals(theme.getEditorForeground(), styledText.getForeground(), "Foreground colors isn't equals"); assertNull(theme.getEditorSelectionBackground(), "System default selection background should be null"); @@ -89,7 +89,7 @@ public void systemDefaultEditorColorTest() throws IOException, PartInitException } @Test - public void userDefinedEditorColorTest() throws Exception { + void userDefinedEditorColorTest() throws Exception { String testColorVal = "255,128,0"; Color testColor = new Color(Display.getCurrent(), 255, 128, 0); IPreferenceStore prefs = new ScopedPreferenceStore(InstanceScope.INSTANCE, "org.eclipse.ui.editors"); @@ -108,7 +108,7 @@ public void userDefinedEditorColorTest() throws Exception { String themeId = manager.getDefaultTheme().getId(); ITheme theme = manager.getThemeById(themeId); - assertEquals(themeId, SolarizedLight, "Default light theme isn't set"); + assertEquals(SolarizedLight, themeId, "Default light theme isn't set"); assertEquals(styledText.getBackground(), testColor, "Background color should be user defined"); assertEquals(theme.getEditorForeground(), styledText.getForeground(), "Foreground colors should be "); diff --git a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/themes/ThemeManagerTest.java b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/themes/ThemeManagerTest.java similarity index 89% rename from org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/themes/ThemeManagerTest.java rename to org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/themes/ThemeManagerTest.java index 02abdfa07..d4af15ea7 100644 --- a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/themes/ThemeManagerTest.java +++ b/org.eclipse.tm4e.ui.tests/src/main/java/org/eclipse/tm4e/ui/themes/ThemeManagerTest.java @@ -1,71 +1,71 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.themes; - -import static org.junit.jupiter.api.Assertions.*; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -/** - * Test for theme manager. - * - */ -public class ThemeManagerTest implements ThemeIdConstants { - - private IThemeManager manager; - - @BeforeEach - public void init() { - manager = new MockThemeManager(); - - // Register theme - manager.registerTheme(new Theme(SolarizedLight, "./themes/SolarizedLight.css", "SolarizedLight", false, true)); - manager.registerTheme(new Theme(Light, "./themes/Light.css", "Light", false, false)); - manager.registerTheme(new Theme(Dark, "./themes/Dark.css", "Dark", true, true)); - manager.registerTheme(new Theme(Monokai, "./themes/Monokai.css", "Monokai", true, false)); - } - - - @Test - public void themes() { - // All themes - ITheme[] themes = manager.getThemes(); - assertNotNull(themes); - assertEquals(4, themes.length); - } - - @Test - public void defaultThemeAssociation() { - // Default theme - ITheme theme = manager.getDefaultTheme(); - assertNotNull(theme); - assertEquals(SolarizedLight, theme.getId()); - } - - @Test - public void darkThemes() { - // All themes for Dark E4 CSS Theme - ITheme[] darkThemes = manager.getThemes(true); - assertNotNull(darkThemes); - assertEquals(2, darkThemes.length); - assertEquals(Dark, darkThemes[0].getId()); - assertEquals(Monokai, darkThemes[1].getId()); - - // All themes for Other E4 CSS Theme - ITheme[] otherThemes = manager.getThemes(false); - assertNotNull(otherThemes); - assertEquals(2, otherThemes.length); - assertEquals(SolarizedLight, otherThemes[0].getId()); - assertEquals(Light, otherThemes[1].getId()); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.themes; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * Test for theme manager. + * + */ +class ThemeManagerTest implements ThemeIdConstants { + + private IThemeManager manager; + + @BeforeEach + public void init() { + manager = new MockThemeManager(); + + // Register theme + manager.registerTheme(new Theme(SolarizedLight, "./themes/SolarizedLight.css", "SolarizedLight", false, true)); + manager.registerTheme(new Theme(Light, "./themes/Light.css", "Light", false, false)); + manager.registerTheme(new Theme(Dark, "./themes/Dark.css", "Dark", true, true)); + manager.registerTheme(new Theme(Monokai, "./themes/Monokai.css", "Monokai", true, false)); + } + + + @Test + void themes() { + // All themes + ITheme[] themes = manager.getThemes(); + assertNotNull(themes); + assertEquals(4, themes.length); + } + + @Test + void defaultThemeAssociation() { + // Default theme + ITheme theme = manager.getDefaultTheme(); + assertNotNull(theme); + assertEquals(SolarizedLight, theme.getId()); + } + + @Test + void darkThemes() { + // All themes for Dark E4 CSS Theme + ITheme[] darkThemes = manager.getThemes(true); + assertNotNull(darkThemes); + assertEquals(2, darkThemes.length); + assertEquals(Dark, darkThemes[0].getId()); + assertEquals(Monokai, darkThemes[1].getId()); + + // All themes for Other E4 CSS Theme + ITheme[] otherThemes = manager.getThemes(false); + assertNotNull(otherThemes); + assertEquals(2, otherThemes.length); + assertEquals(SolarizedLight, otherThemes[0].getId()); + assertEquals(Light, otherThemes[1].getId()); + } +} diff --git a/org.eclipse.tm4e.ui.tests/src/test/resources/org/eclipse/textmate4e/ui/text/Solarized-light.css b/org.eclipse.tm4e.ui.tests/src/main/resources/org/eclipse/textmate4e/ui/text/Solarized-light.css similarity index 100% rename from org.eclipse.tm4e.ui.tests/src/test/resources/org/eclipse/textmate4e/ui/text/Solarized-light.css rename to org.eclipse.tm4e.ui.tests/src/main/resources/org/eclipse/textmate4e/ui/text/Solarized-light.css diff --git a/org.eclipse.tm4e.ui/.classpath b/org.eclipse.tm4e.ui/.classpath index 1ee1e0930..3aa82bf3a 100644 --- a/org.eclipse.tm4e.ui/.classpath +++ b/org.eclipse.tm4e.ui/.classpath @@ -6,8 +6,35 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.eclipse.tm4e.ui/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.tm4e.ui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..6b99f88fc --- /dev/null +++ b/org.eclipse.tm4e.ui/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,518 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.APILeak=warning +org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning +org.eclipse.jdt.core.compiler.problem.fallthroughCase=info +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=info +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=info +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=enabled +org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=11 +org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false +org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false +org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package=49 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter=0 +org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type=49 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assertion_message=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0 +org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_record_components=16 +org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_type_annotations=0 +org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0 +org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch=0 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_constructor=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_record_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false +org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true +org.eclipse.jdt.core.formatter.comment.format_block_comments=false +org.eclipse.jdt.core.formatter.comment.format_header=true +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.indent_tag_description=false +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=120 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_not_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false +org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.text_block_indentation=0 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false +org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true +org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true +org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true +org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true +org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/org.eclipse.tm4e.ui/META-INF/MANIFEST.MF b/org.eclipse.tm4e.ui/META-INF/MANIFEST.MF index 9ebf3cd00..417066249 100644 --- a/org.eclipse.tm4e.ui/META-INF/MANIFEST.MF +++ b/org.eclipse.tm4e.ui/META-INF/MANIFEST.MF @@ -4,8 +4,8 @@ Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-Localization: plugin Bundle-SymbolicName: org.eclipse.tm4e.ui;singleton:=true -Bundle-Version: 0.5.0.qualifier -Require-Bundle: org.eclipse.tm4e.core, +Bundle-Version: 0.5.1.qualifier +Require-Bundle: org.eclipse.tm4e.core;bundle-version="0.4.4", org.eclipse.jface.text, org.eclipse.core.runtime, org.eclipse.ui, @@ -14,20 +14,20 @@ Require-Bundle: org.eclipse.tm4e.core, org.eclipse.tm4e.registry, org.eclipse.ui.ide;resolution:=optional, com.google.gson, + com.google.guava, org.eclipse.e4.ui.css.swt.theme, org.eclipse.core.expressions, org.eclipse.ui.workbench.texteditor, - org.eclipse.jdt.annotation;bundle-version="2.2.0";resolution:=optional, org.eclipse.ui.trace;resolution:=optional Bundle-RequiredExecutionEnvironment: JavaSE-11 Export-Package: org.eclipse.tm4e.ui, org.eclipse.tm4e.ui.internal.model;x-friends:="org.eclipse.tm4e.ui.tests", org.eclipse.tm4e.ui.internal.themes;x-friends:="org.eclipse.tm4e.ui.tests", + org.eclipse.tm4e.ui.internal.utils;x-friends:="org.eclipse.tm4e.ui.tests,org.eclipse.tm4e.languageconfiguration", org.eclipse.tm4e.ui.model, org.eclipse.tm4e.ui.text, org.eclipse.tm4e.ui.themes, - org.eclipse.tm4e.ui.themes.css, - org.eclipse.tm4e.ui.utils + org.eclipse.tm4e.ui.themes.css Bundle-Activator: org.eclipse.tm4e.ui.TMUIPlugin Bundle-ActivationPolicy: lazy Import-Package: org.eclipse.core.filebuffers diff --git a/org.eclipse.tm4e.ui/build.properties b/org.eclipse.tm4e.ui/build.properties index 7daa50854..e1332cf9b 100644 --- a/org.eclipse.tm4e.ui/build.properties +++ b/org.eclipse.tm4e.ui/build.properties @@ -1,6 +1,5 @@ source.. = src/main/java/,\ - src/main/resources/,\ - src/test/resources + src/main/resources/ bin.includes = META-INF/,\ .,\ plugin.properties,\ @@ -9,3 +8,9 @@ bin.includes = META-INF/,\ themes/,\ .options,\ about.html + +# https://codeiseasy.wordpress.com/2013/03/08/tycho-and-jdt-null-analysis/ +# JDT Null Analysis for Eclipse +additional.bundles = org.eclipse.jdt.annotation +# JDT Null Analysis types for Tycho +jars.extra.classpath = platform:/plugin/org.eclipse.jdt.annotation diff --git a/org.eclipse.tm4e.ui/pom.xml b/org.eclipse.tm4e.ui/pom.xml index d93101e23..e7b771348 100644 --- a/org.eclipse.tm4e.ui/pom.xml +++ b/org.eclipse.tm4e.ui/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.eclipse.tm4e.ui eclipse-plugin - 0.5.0-SNAPSHOT + 0.5.1-SNAPSHOT org.eclipse org.eclipse.tm4e diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/TMUIPlugin.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/TMUIPlugin.java index 8f7c14597..204e80793 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/TMUIPlugin.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/TMUIPlugin.java @@ -1,138 +1,145 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui; - -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.LogRecord; -import java.util.logging.Logger; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.Status; -import org.eclipse.tm4e.ui.internal.model.TMModelManager; -import org.eclipse.tm4e.ui.internal.snippets.SnippetManager; -import org.eclipse.tm4e.ui.internal.themes.ThemeManager; -import org.eclipse.tm4e.ui.model.ITMModelManager; -import org.eclipse.tm4e.ui.snippets.ISnippetManager; -import org.eclipse.tm4e.ui.themes.ColorManager; -import org.eclipse.tm4e.ui.themes.IThemeManager; -import org.eclipse.ui.plugin.AbstractUIPlugin; -import org.osgi.framework.BundleContext; - -/** - * The activator class controls the plug-in life cycle - */ -public class TMUIPlugin extends AbstractUIPlugin { - - // The plug-in ID - public static final String PLUGIN_ID = "org.eclipse.tm4e.ui"; //$NON-NLS-1$ - private static final String TRACE_ID = PLUGIN_ID + "/trace"; //$NON-NLS-1$ - - // The shared instance - private static TMUIPlugin plugin; - - /** - * The constructor - */ - public TMUIPlugin() { - } - - public void trace(String message) { - if (Boolean.parseBoolean(Platform.getDebugOption(TRACE_ID))) { - getLog().log(new Status(IStatus.INFO, PLUGIN_ID, message)); - } - } - - @Override - public void start(BundleContext context) throws Exception { - super.start(context); - plugin = this; - boolean isDebugOn = Boolean.parseBoolean(Platform.getDebugOption(TRACE_ID)); - if (isDebugOn) { - Logger tm4eCoreLogger = Logger.getLogger("org.eclipse.tm4e"); - tm4eCoreLogger.setLevel(Level.FINEST); - tm4eCoreLogger.addHandler(new Handler() { - - @Override public void publish(LogRecord record) { - TMUIPlugin.getDefault().getLog().log(new Status( - toSeverity(record.getLevel()), - "org.eclipse.tm4e.core", - record.getMessage() - )); - } - - private int toSeverity(Level level) { - if (level.intValue() >= Level.SEVERE.intValue()) { - return IStatus.ERROR; - } - if (level.intValue() >= Level.WARNING.intValue()) { - return IStatus.WARNING; - } - return IStatus.INFO; - } - - @Override public void flush() { - // nothing to do - } - - @Override public void close() throws SecurityException { - // nothing to do - } - }); - } - } - - @Override - public void stop(BundleContext context) throws Exception { - ColorManager.getInstance().dispose(); - plugin = null; - super.stop(context); - } - - /** - * Returns the shared instance - * - * @return the shared instance - */ - public static TMUIPlugin getDefault() { - return plugin; - } - - /** - * Returns the TextMate model manager. - * - * @return the TextMate model manager. - */ - public static ITMModelManager getTMModelManager() { - return TMModelManager.getInstance(); - } - - /** - * Returns the TextMate themes manager. - * - * @return the TextMate themes manager. - */ - public static IThemeManager getThemeManager() { - return ThemeManager.getInstance(); - } - - /** - * Returns the Snippet manager. - * - * @return the Snippet manager. - */ - public static ISnippetManager getSnippetManager() { - return SnippetManager.getInstance(); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui; + +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.ui.internal.model.TMModelManager; +import org.eclipse.tm4e.ui.internal.snippets.SnippetManager; +import org.eclipse.tm4e.ui.internal.themes.ThemeManager; +import org.eclipse.tm4e.ui.model.ITMModelManager; +import org.eclipse.tm4e.ui.snippets.ISnippetManager; +import org.eclipse.tm4e.ui.themes.ColorManager; +import org.eclipse.tm4e.ui.themes.IThemeManager; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class TMUIPlugin extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.tm4e.ui"; //$NON-NLS-1$ + private static final String TRACE_ID = PLUGIN_ID + "/trace"; //$NON-NLS-1$ + + // The shared instance + @Nullable + private static volatile TMUIPlugin plugin; + + public static void log(IStatus status) { + final var plugin = TMUIPlugin.plugin; + if (plugin != null) { + plugin.getLog().log(status); + } + } + + public static void trace(final String message) { + if (Boolean.parseBoolean(Platform.getDebugOption(TRACE_ID))) { + log(new Status(IStatus.INFO, PLUGIN_ID, message)); + } + } + + @Override + public void start(@Nullable final BundleContext context) throws Exception { + super.start(context); + plugin = this; + final boolean isDebugOn = Boolean.parseBoolean(Platform.getDebugOption(TRACE_ID)); + if (isDebugOn) { + final Logger tm4eCoreLogger = Logger.getLogger("org.eclipse.tm4e"); + tm4eCoreLogger.setLevel(Level.FINEST); + tm4eCoreLogger.addHandler(new Handler() { + + @Override + public void publish(@Nullable final LogRecord record) { + if (record != null) { + log(new Status( + toSeverity(record.getLevel()), + "org.eclipse.tm4e.core", + record.getMessage())); + } + } + + private int toSeverity(final Level level) { + if (level.intValue() >= Level.SEVERE.intValue()) { + return IStatus.ERROR; + } + if (level.intValue() >= Level.WARNING.intValue()) { + return IStatus.WARNING; + } + return IStatus.INFO; + } + + @Override + public void flush() { + // nothing to do + } + + @Override + public void close() throws SecurityException { + // nothing to do + } + }); + } + } + + @Override + public void stop(@Nullable final BundleContext context) throws Exception { + ColorManager.getInstance().dispose(); + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + @Nullable + public static TMUIPlugin getDefault() { + return plugin; + } + + /** + * Returns the TextMate model manager. + * + * @return the TextMate model manager. + */ + public static ITMModelManager getTMModelManager() { + return TMModelManager.getInstance(); + } + + /** + * Returns the TextMate themes manager. + * + * @return the TextMate themes manager. + */ + public static IThemeManager getThemeManager() { + return ThemeManager.getInstance(); + } + + /** + * Returns the Snippet manager. + * + * @return the Snippet manager. + */ + public static ISnippetManager getSnippetManager() { + return SnippetManager.getInstance(); + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/TMPropertyTester.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/TMPropertyTester.java index a90881834..88c9ceb92 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/TMPropertyTester.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/TMPropertyTester.java @@ -1,39 +1,40 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal; - -import org.eclipse.core.expressions.PropertyTester; -import org.eclipse.tm4e.ui.text.TMPresentationReconciler; -import org.eclipse.ui.IEditorPart; - -/** - * An Eclipse property tester to check if a given editor part is linked to the - * {@link TMPresentationReconciler}. - * - */ -public class TMPropertyTester extends PropertyTester { - - private static final String CAN_SUPPORT_TEXT_MATE = "canSupportTextMate"; - - @Override - public boolean test(Object receiver, String property, Object[] args, Object expectedValue) { - if (CAN_SUPPORT_TEXT_MATE.equals(property)) { - if (receiver instanceof IEditorPart) { - IEditorPart editorPart = (IEditorPart) receiver; - TMPresentationReconciler reconciler = TMPresentationReconciler.getTMPresentationReconciler(editorPart); - return reconciler != null && reconciler.isEnabled(); - } - } - return false; - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal; + +import org.eclipse.core.expressions.PropertyTester; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.ui.text.TMPresentationReconciler; +import org.eclipse.ui.IEditorPart; + +/** + * An Eclipse property tester to check if a given editor part is linked to the + * {@link TMPresentationReconciler}. + * + */ +public final class TMPropertyTester extends PropertyTester { + + private static final String CAN_SUPPORT_TEXT_MATE = "canSupportTextMate"; + + @Override + public boolean test(@Nullable final Object receiver, @Nullable final String property, + final Object @Nullable [] args, @Nullable final Object expectedValue) { + if (CAN_SUPPORT_TEXT_MATE.equals(property)) { + if (receiver instanceof IEditorPart) { + final var editorPart = (IEditorPart) receiver; + final var reconciler = TMPresentationReconciler.getTMPresentationReconciler(editorPart); + return reconciler != null && reconciler.isEnabled(); + } + } + return false; + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/TMUIMessages.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/TMUIMessages.java index ae490de7b..f45db0e7f 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/TMUIMessages.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/TMUIMessages.java @@ -1,93 +1,94 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal; - -import org.eclipse.osgi.util.NLS; - -/** - * Helper class to get NLSed messages. - * - */ -public class TMUIMessages extends NLS { - - private static final String BUNDLE_NAME = "org.eclipse.tm4e.ui.internal.TMUIMessages"; //$NON-NLS-1$ - - // Buttons - public static String Button_new; - public static String Button_edit; - public static String Button_remove; - public static String Button_browse_FileSystem; - public static String Button_browse_Workspace; - - // TextMate preferences page - public static String TextMatePreferencePage_GrammarRelatedLink; - public static String TextMatePreferencePage_LanguageConfigurationRelatedLink; - public static String TextMatePreferencePage_ThemeRelatedLink; - - // Grammar preferences page - public static String GrammarPreferencePage_title; - public static String GrammarPreferencePage_description; - public static String GrammarPreferencePage_column_scopeName; - public static String GrammarPreferencePage_column_path; - public static String GrammarPreferencePage_column_pluginId; - public static String GrammarPreferencePage_tab_general_text; - public static String GrammarInfoWidget_name_text; - public static String GrammarInfoWidget_scopeName_text; - public static String GrammarInfoWidget_fileTypes_text; - public static String GrammarPreferencePage_tab_contentType_text; - public static String GrammarPreferencePage_tab_theme_text; - public static String GrammarPreferencePage_tab_injection_text; - public static String GrammarPreferencePage_preview; - - // Theme preferences page - public static String ThemePreferencePage_title; - public static String ThemePreferencePage_description; - public static String ThemePreferencePage_column_name; - public static String ThemePreferencePage_column_path; - public static String ThemePreferencePage_column_pluginId; - public static String ThemePreferencePage_darkThemeButton_label; - public static String ThemePreferencePage_defaultThemeButton_label; - public static String ThemePreferencePage_preview; - - // Widgets - public static String ContentTypesBindingWidget_description; - public static String ThemeAssociationsWidget_description; - public static String ThemeAssociationsWidget_remove_dialog_title; - public static String ThemeAssociationsWidget_remove_dialog_message; - public static String ThemeAssociationLabelProvider_light; - public static String ThemeAssociationLabelProvider_dark; - - // Wizards - public static String SelectGrammarWizardPage_title; - public static String SelectGrammarWizardPage_description; - public static String SelectGrammarWizardPage_file_label; - public static String SelectGrammarWizardPage_file_error_required; - public static String SelectGrammarWizardPage_file_error_load; - public static String SelectGrammarWizardPage_file_error_invalid; - - public static String CreateThemeAssociationWizardPage_title; - public static String CreateThemeAssociationWizardPage_description; - public static String CreateThemeAssociationWizardPage_theme_text; - public static String CreateThemeAssociationWizardPage_grammar_text; - public static String CreateThemeAssociationWizardPage_theme_error_required; - public static String CreateThemeAssociationWizardPage_grammar_error_required; - public static String CreateThemeAssociationWizardPage_whenDark_text; - - // TMPresentationReconciler register dialog confirmation - public static String TMPresentationReconciler_register_dialog_title; - public static String TMPresentationReconciler_register_dialog_message; - - static { - NLS.initializeMessages(BUNDLE_NAME, TMUIMessages.class); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.osgi.util.NLS; + +/** + * Helper class to get NLSed messages. + */ +@NonNullByDefault({}) +public final class TMUIMessages extends NLS { + + private static final String BUNDLE_NAME = "org.eclipse.tm4e.ui.internal.TMUIMessages"; //$NON-NLS-1$ + + // Buttons + public static String Button_new; + public static String Button_edit; + public static String Button_remove; + public static String Button_browse_FileSystem; + public static String Button_browse_Workspace; + + // TextMate preferences page + public static String TextMatePreferencePage_GrammarRelatedLink; + public static String TextMatePreferencePage_LanguageConfigurationRelatedLink; + public static String TextMatePreferencePage_ThemeRelatedLink; + + // Grammar preferences page + public static String GrammarPreferencePage_title; + public static String GrammarPreferencePage_description; + public static String GrammarPreferencePage_column_scopeName; + public static String GrammarPreferencePage_column_path; + public static String GrammarPreferencePage_column_pluginId; + public static String GrammarPreferencePage_tab_general_text; + public static String GrammarInfoWidget_name_text; + public static String GrammarInfoWidget_scopeName_text; + public static String GrammarInfoWidget_fileTypes_text; + public static String GrammarPreferencePage_tab_contentType_text; + public static String GrammarPreferencePage_tab_theme_text; + public static String GrammarPreferencePage_tab_injection_text; + public static String GrammarPreferencePage_preview; + + // Theme preferences page + public static String ThemePreferencePage_title; + public static String ThemePreferencePage_description; + public static String ThemePreferencePage_column_name; + public static String ThemePreferencePage_column_path; + public static String ThemePreferencePage_column_pluginId; + public static String ThemePreferencePage_darkThemeButton_label; + public static String ThemePreferencePage_defaultThemeButton_label; + public static String ThemePreferencePage_preview; + + // Widgets + public static String ContentTypesBindingWidget_description; + public static String ThemeAssociationsWidget_description; + public static String ThemeAssociationsWidget_remove_dialog_title; + public static String ThemeAssociationsWidget_remove_dialog_message; + public static String ThemeAssociationLabelProvider_light; + public static String ThemeAssociationLabelProvider_dark; + + // Wizards + public static String SelectGrammarWizardPage_title; + public static String SelectGrammarWizardPage_description; + public static String SelectGrammarWizardPage_file_label; + public static String SelectGrammarWizardPage_file_error_required; + public static String SelectGrammarWizardPage_file_error_load; + public static String SelectGrammarWizardPage_file_error_invalid; + + public static String CreateThemeAssociationWizardPage_title; + public static String CreateThemeAssociationWizardPage_description; + public static String CreateThemeAssociationWizardPage_theme_text; + public static String CreateThemeAssociationWizardPage_grammar_text; + public static String CreateThemeAssociationWizardPage_theme_error_required; + public static String CreateThemeAssociationWizardPage_grammar_error_required; + public static String CreateThemeAssociationWizardPage_whenDark_text; + + // TMPresentationReconciler register dialog confirmation + public static String TMPresentationReconciler_register_dialog_title; + public static String TMPresentationReconciler_register_dialog_message; + + static { + NLS.initializeMessages(BUNDLE_NAME, TMUIMessages.class); + } + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/TMUIMessages.properties b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/TMUIMessages.properties index 0066ccf12..f132b9914 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/TMUIMessages.properties +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/TMUIMessages.properties @@ -6,7 +6,7 @@ # http://www.eclipse.org/legal/epl-v10.html # # Contributors: -# Angelo Zerr - Initial API and implementation +# Angelo Zerr - Initial API and implementation ############################################################################### # Buttons @@ -18,7 +18,7 @@ Button_browse_Workspace=Browse Workspace... # preference page TextMatePreferencePage_GrammarRelatedLink=See ''{0}'' for associating editors with grammars. -TextMatePreferencePage_LanguageConfigurationRelatedLink=See ''{0}'' for associating editors with language configurations. +TextMatePreferencePage_LanguageConfigurationRelatedLink=See ''{0}'' for associating editors with language configurations. TextMatePreferencePage_ThemeRelatedLink=See ''{0}'' for associating editors with themes. GrammarPreferencePage_title=TextMate grammars @@ -52,19 +52,19 @@ ThemeAssociationLabelProvider_dark=Use ''{0}'' theme with Eclipse 'Dark' theme. GrammarInfoWidget_name_text=Name: GrammarInfoWidget_scopeName_text=Scope: GrammarInfoWidget_fileTypes_text=File types: - + # Wizards SelectGrammarWizardPage_title=Specify the TextMate grammar file -SelectGrammarWizardPage_description=Specify the TextMate grammar file *.tmLanguage, *.json (VSCode format) to import. +SelectGrammarWizardPage_description=Specify the TextMate grammar file *.tmLanguage, *.json (VSCode format), *.YAML-tmLanguage, *.yaml, *.yml to import. SelectGrammarWizardPage_file_label=File: -SelectGrammarWizardPage_file_error_required=TextMate grammar file is required. +SelectGrammarWizardPage_file_error_required=TextMate grammar file is required. SelectGrammarWizardPage_file_error_load=Error while loading the TextMate grammar file: "{0}". SelectGrammarWizardPage_file_error_invalid=The file is not a TextMate grammar file. It cannot retrieve the scope name. -CreateThemeAssociationWizardPage_title=Specify the theme to use with a given grammar +CreateThemeAssociationWizardPage_title=Specify the theme to use with a given grammar CreateThemeAssociationWizardPage_description=Choose the theme to use for your grammar when an E4 Theme is activated. -CreateThemeAssociationWizardPage_theme_text=Use the theme: -CreateThemeAssociationWizardPage_grammar_text= with the grammar: +CreateThemeAssociationWizardPage_theme_text=Use the theme: +CreateThemeAssociationWizardPage_grammar_text= with the grammar: CreateThemeAssociationWizardPage_theme_error_required=Theme is required CreateThemeAssociationWizardPage_grammar_error_required=Grammar is required CreateThemeAssociationWizardPage_whenDark_text=when Eclipse Dark theme is activated? diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/menus/ThemeContribution.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/menus/ThemeContribution.java index 311ab2837..4b89e87a6 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/menus/ThemeContribution.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/menus/ThemeContribution.java @@ -1,104 +1,112 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.menus; - -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.core.expressions.IEvaluationContext; -import org.eclipse.jface.action.Action; -import org.eclipse.jface.action.ActionContributionItem; -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.action.IContributionItem; -import org.eclipse.tm4e.ui.TMUIPlugin; -import org.eclipse.tm4e.ui.text.TMPresentationReconciler; -import org.eclipse.tm4e.ui.themes.ITheme; -import org.eclipse.tm4e.ui.themes.IThemeAssociation; -import org.eclipse.tm4e.ui.themes.IThemeManager; -import org.eclipse.tm4e.ui.themes.ThemeAssociation; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.ISources; -import org.eclipse.ui.actions.CompoundContributionItem; -import org.eclipse.ui.handlers.IHandlerService; -import org.eclipse.ui.menus.IWorkbenchContribution; -import org.eclipse.ui.services.IServiceLocator; -import org.osgi.service.prefs.BackingStoreException; - -/** - * Contribute "Switch to theme" menu item with list of available themes. - * - */ -public class ThemeContribution extends CompoundContributionItem implements IWorkbenchContribution { - - private IHandlerService handlerService; - - @Override - public void initialize(IServiceLocator serviceLocator) { - handlerService = serviceLocator.getService(IHandlerService.class); - } - - @Override - protected IContributionItem[] getContributionItems() { - List items = new ArrayList(); - if (handlerService != null) { - IEditorPart editorPart = getActivePart(handlerService.getCurrentState()); - if (editorPart != null) { - IThemeManager manager = TMUIPlugin.getThemeManager(); - boolean dark = manager.isDarkEclipseTheme(); - ITheme[] themes = manager.getThemes(); - TMPresentationReconciler presentationReconciler = TMPresentationReconciler.getTMPresentationReconciler(editorPart); - if (themes != null && presentationReconciler != null) { - String scopeName = presentationReconciler.getGrammar().getScopeName(); - ITheme selectedTheme = manager.getThemeForScope(scopeName, dark); - for (ITheme theme : themes) { - IAction action = createAction(scopeName, theme, dark); - if (theme.equals(selectedTheme)) { - action.setChecked(true); - } - IContributionItem item = new ActionContributionItem(action); - items.add(item); - } - } - - } - } - return items.toArray(new IContributionItem[items.size()]); - } - - private Action createAction(final String scopeName, final ITheme theme, boolean whenDark) { - return new Action(theme.getName()) { - @Override - public void run() { - IThemeManager manager = TMUIPlugin.getThemeManager(); - IThemeAssociation association = new ThemeAssociation(theme.getId(), scopeName, whenDark); - manager.registerThemeAssociation(association); - try { - manager.save(); - } catch (BackingStoreException e) { - e.printStackTrace(); - } - } - }; - } - - private static IEditorPart getActivePart(IEvaluationContext context) { - if (context == null) - return null; - - Object activePart = context.getVariable(ISources.ACTIVE_PART_NAME); - if ((activePart instanceof IEditorPart)) - return (IEditorPart) activePart; - - return null; - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.menus; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.expressions.IEvaluationContext; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.ActionContributionItem; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IContributionItem; +import org.eclipse.tm4e.ui.TMUIPlugin; +import org.eclipse.tm4e.ui.text.TMPresentationReconciler; +import org.eclipse.tm4e.ui.themes.ITheme; +import org.eclipse.tm4e.ui.themes.IThemeAssociation; +import org.eclipse.tm4e.ui.themes.IThemeManager; +import org.eclipse.tm4e.ui.themes.ThemeAssociation; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.ISources; +import org.eclipse.ui.actions.CompoundContributionItem; +import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.menus.IWorkbenchContribution; +import org.eclipse.ui.services.IServiceLocator; +import org.osgi.service.prefs.BackingStoreException; + +/** + * Contribute "Switch to theme" menu item with list of available themes. + * + */ +public final class ThemeContribution extends CompoundContributionItem implements IWorkbenchContribution { + + @Nullable + private IHandlerService handlerService; + + @Override + public void initialize(@Nullable final IServiceLocator serviceLocator) { + assert serviceLocator != null; + handlerService = serviceLocator.getService(IHandlerService.class); + } + + @Override + protected IContributionItem[] getContributionItems() { + final List items = new ArrayList<>(); + if (handlerService != null) { + final IEditorPart editorPart = getActivePart(handlerService.getCurrentState()); + if (editorPart != null) { + final IThemeManager manager = TMUIPlugin.getThemeManager(); + final boolean dark = manager.isDarkEclipseTheme(); + final ITheme[] themes = manager.getThemes(); + final TMPresentationReconciler presentationReconciler = TMPresentationReconciler + .getTMPresentationReconciler(editorPart); + if (presentationReconciler != null) { + final var grammar = presentationReconciler.getGrammar(); + if (grammar != null) { + final String scopeName = grammar.getScopeName(); + final ITheme selectedTheme = manager.getThemeForScope(scopeName, dark); + for (final ITheme theme : themes) { + final IAction action = createAction(scopeName, theme, dark); + if (theme.equals(selectedTheme)) { + action.setChecked(true); + } + final IContributionItem item = new ActionContributionItem(action); + items.add(item); + } + } + } + + } + } + return items.toArray(IContributionItem[]::new); + } + + private Action createAction(final String scopeName, final ITheme theme, final boolean whenDark) { + return new Action(theme.getName()) { + @Override + public void run() { + final IThemeManager manager = TMUIPlugin.getThemeManager(); + final IThemeAssociation association = new ThemeAssociation(theme.getId(), scopeName, whenDark); + manager.registerThemeAssociation(association); + try { + manager.save(); + } catch (final BackingStoreException e) { + e.printStackTrace(); + } + } + }; + } + + @Nullable + private static IEditorPart getActivePart(@Nullable final IEvaluationContext context) { + if (context == null) + return null; + + final Object activePart = context.getVariable(ISources.ACTIVE_PART_NAME); + if ((activePart instanceof IEditorPart)) + return (IEditorPart) activePart; + + return null; + } + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/menus/package-info.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/menus/package-info.java new file mode 100644 index 000000000..a875d9ce5 --- /dev/null +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/menus/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.ui.internal.menus; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/DocumentHelper.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/DocumentHelper.java index b6eddca6c..008e1494e 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/DocumentHelper.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/DocumentHelper.java @@ -1,59 +1,59 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.model; - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.DocumentEvent; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.Region; - -/** - * Utilities class for {@link IDocument}. - * - */ -public class DocumentHelper { - - public static int getStartLine(DocumentEvent event) throws BadLocationException { - return event.getDocument().getLineOfOffset(event.getOffset()); - } - - public static int getEndLine(DocumentEvent event, boolean documentAboutToBeChanged) throws BadLocationException { - int length = documentAboutToBeChanged ? event.getLength() : event.getText().length(); - return event.getDocument().getLineOfOffset(event.getOffset() + length); - } - - public static boolean isRemove(DocumentEvent event) { - return event.getText() == null || event.getText().length() == 0; - } - - public static boolean isInsert(DocumentEvent event) { - return event.getLength() == 0 && event.getText() != null; - } - - public static String getLineText(IDocument document, int line, boolean withLineDelimiter) - throws BadLocationException { - int lo = document.getLineOffset(line); - int ll = document.getLineLength(line); - if (!withLineDelimiter) { - String delim = document.getLineDelimiter(line); - ll = ll - (delim != null ? delim.length() : 0); - } - return document.get(lo, ll); - } - - public static IRegion getRegion(IDocument document, int fromLine, int toLine) throws BadLocationException { - int startOffset = document.getLineOffset(fromLine); - int endOffset = document.getLineOffset(toLine) + document.getLineLength(toLine); - return new Region(startOffset, endOffset - startOffset); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.model; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Region; + +/** + * Utilities class for {@link IDocument}. + * + */ +final class DocumentHelper { + + static int getStartLine(final DocumentEvent event) throws BadLocationException { + return event.getDocument().getLineOfOffset(event.getOffset()); + } + + static int getEndLine(final DocumentEvent event, final boolean documentAboutToBeChanged) throws BadLocationException { + final int length = documentAboutToBeChanged ? event.getLength() : event.getText().length(); + return event.getDocument().getLineOfOffset(event.getOffset() + length); + } + + static boolean isRemove(final DocumentEvent event) { + return event.getText() == null || event.getText().isEmpty(); + } + + static boolean isInsert(final DocumentEvent event) { + return event.getLength() == 0 && event.getText() != null; + } + + static String getLineText(final IDocument document, final int line, final boolean withLineDelimiter) + throws BadLocationException { + final int lo = document.getLineOffset(line); + int ll = document.getLineLength(line); + if (!withLineDelimiter) { + final String delim = document.getLineDelimiter(line); + ll = ll - (delim != null ? delim.length() : 0); + } + return document.get(lo, ll); + } + + private static IRegion getRegion(final IDocument document, final int fromLine, final int toLine) throws BadLocationException { + final int startOffset = document.getLineOffset(fromLine); + final int endOffset = document.getLineOffset(toLine) + document.getLineLength(toLine); + return new Region(startOffset, endOffset - startOffset); + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/DocumentInputStream.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/DocumentInputStream.java index eb5b9cd81..924ff8980 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/DocumentInputStream.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/DocumentInputStream.java @@ -1,50 +1,47 @@ -/******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - * QNX Software System - *******************************************************************************/ -package org.eclipse.tm4e.ui.internal.model; - -import java.io.IOException; -import java.io.InputStream; - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.IDocument; -/** - * Input stream which reads from a document - */ -public class DocumentInputStream extends InputStream { - - private IDocument fDocument; - private int fCurrPos; - - public DocumentInputStream(IDocument document) { - fDocument= document; - fCurrPos= 0; - } - - public IDocument getDocument() { - return fDocument; - } - - /** - * {@inheritDoc} - */ - @Override - public int read() throws IOException { - try { - if (fCurrPos < fDocument.getLength()) { - return fDocument.getChar(fCurrPos++); - } - } catch (BadLocationException e) { - } - return -1; - } - +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * QNX Software System + *******************************************************************************/ +package org.eclipse.tm4e.ui.internal.model; + +import java.io.IOException; +import java.io.InputStream; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +/** + * Input stream which reads from a document + */ +public final class DocumentInputStream extends InputStream { + + private final IDocument fDocument; + private int fCurrPos = 0; + + public DocumentInputStream(final IDocument document) { + fDocument= document; + } + + public IDocument getDocument() { + return fDocument; + } + + @Override + public int read() throws IOException { + try { + if (fCurrPos < fDocument.getLength()) { + return fDocument.getChar(fCurrPos++); + } + } catch (final BadLocationException e) { + // ignore + } + return -1; + } + } \ No newline at end of file diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/DocumentLineList.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/DocumentLineList.java index 5e0a86d6b..fdc97a3e7 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/DocumentLineList.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/DocumentLineList.java @@ -1,110 +1,114 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.model; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.DocumentEvent; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IDocumentListener; -import org.eclipse.tm4e.core.model.AbstractLineList; -import org.eclipse.tm4e.ui.TMUIPlugin; - -/** - * TextMate {@link AbstractLineList} implementation with Eclipse - * {@link IDocument}. - * - * Goal of this class is to synchronize Eclipse {@link DocumentEvent} with - * TextMate model lines. - * - */ -public class DocumentLineList extends AbstractLineList { - - private final IDocument document; - private InternalListener listener; - - public DocumentLineList(IDocument document) { - this.document = document; - this.listener = new InternalListener(); - document.addDocumentListener(listener); - for (int i = 0; i < document.getNumberOfLines(); i++) { - addLine(i); - } - } - - private class InternalListener implements IDocumentListener { - - @Override - public void documentAboutToBeChanged(DocumentEvent event) { - try { - if (!DocumentHelper.isInsert(event)) { - // Remove or Replace (Remove + Insert) - removeLine(event); - } - } catch (BadLocationException e) { - e.printStackTrace(); - } - } - - private void removeLine(DocumentEvent event) throws BadLocationException { - int startLine = DocumentHelper.getStartLine(event); - int endLine = DocumentHelper.getEndLine(event, true); - for (int i = endLine; i > startLine; i--) { - DocumentLineList.this.removeLine(i); - } - } - - @Override - public void documentChanged(DocumentEvent event) { - try { - int startLine = DocumentHelper.getStartLine(event); - if (!DocumentHelper.isRemove(event)) { - int endLine = DocumentHelper.getEndLine(event, false); - // Insert new lines - for (int i = startLine; i < endLine; i++) { - DocumentLineList.this.addLine(i + 1); - } - if (startLine == endLine) { - DocumentLineList.this.updateLine(startLine); - } - } else { - // Update line - DocumentLineList.this.updateLine(startLine); - } - invalidateLine(startLine); - } catch (BadLocationException e) { - TMUIPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); - } - } - } - - @Override - public int getNumberOfLines() { - return document.getNumberOfLines(); - } - - @Override - public String getLineText(int line) throws Exception { - return DocumentHelper.getLineText(document, line, false); - } - - @Override - public int getLineLength(int line) throws Exception { - return document.getLineLength(line); - } - - @Override - public void dispose() { - document.removeDocumentListener(listener); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.model; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentListener; +import org.eclipse.tm4e.core.model.AbstractLineList; +import org.eclipse.tm4e.ui.TMUIPlugin; + +/** + * TextMate {@link AbstractLineList} implementation with Eclipse + * {@link IDocument}. + * + * Goal of this class is to synchronize Eclipse {@link DocumentEvent} with + * TextMate model lines. + * + */ +final class DocumentLineList extends AbstractLineList { + + private final IDocument document; + private final InternalListener listener = new InternalListener(); + + DocumentLineList(final IDocument document) { + this.document = document; + document.addDocumentListener(listener); + for (int i = 0; i < document.getNumberOfLines(); i++) { + addLine(i); + } + } + + private final class InternalListener implements IDocumentListener { + + @Override + public void documentAboutToBeChanged(@Nullable final DocumentEvent event) { + if (event == null) + return; + try { + if (!DocumentHelper.isInsert(event)) { + // Remove or Replace (Remove + Insert) + removeLine(event); + } + } catch (final BadLocationException e) { + e.printStackTrace(); + } + } + + private void removeLine(final DocumentEvent event) throws BadLocationException { + final int startLine = DocumentHelper.getStartLine(event); + final int endLine = DocumentHelper.getEndLine(event, true); + for (int i = endLine; i > startLine; i--) { + DocumentLineList.this.removeLine(i); + } + } + + @Override + public void documentChanged(@Nullable final DocumentEvent event) { + if (event == null) + return; + try { + final int startLine = DocumentHelper.getStartLine(event); + if (!DocumentHelper.isRemove(event)) { + final int endLine = DocumentHelper.getEndLine(event, false); + // Insert new lines + for (int i = startLine; i < endLine; i++) { + DocumentLineList.this.addLine(i + 1); + } + if (startLine == endLine) { + DocumentLineList.this.updateLine(startLine); + } + } else { + // Update line + DocumentLineList.this.updateLine(startLine); + } + invalidateLine(startLine); + } catch (final BadLocationException e) { + TMUIPlugin.log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); + } + } + } + + @Override + public int getNumberOfLines() { + return document.getNumberOfLines(); + } + + @Override + public String getLineText(final int line) throws Exception { + return DocumentHelper.getLineText(document, line, false); + } + + @Override + public int getLineLength(final int line) throws Exception { + return document.getLineLength(line); + } + + @Override + public void dispose() { + document.removeDocumentListener(listener); + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/TMDocumentModel.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/TMDocumentModel.java index 35e7f9d80..98efa1abc 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/TMDocumentModel.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/TMDocumentModel.java @@ -9,22 +9,22 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.ui.internal.model; - +package org.eclipse.tm4e.ui.internal.model; + import org.eclipse.jface.text.IDocument; -import org.eclipse.tm4e.core.model.TMModel; - -public class TMDocumentModel extends TMModel { - - private IDocument document; - - public TMDocumentModel(IDocument document) { - super(new DocumentLineList(document)); - this.document = document; - } - - public IDocument getDocument() { - return document; - } - -} +import org.eclipse.tm4e.core.model.TMModel; + +public final class TMDocumentModel extends TMModel { + + private final IDocument document; + + public TMDocumentModel(final IDocument document) { + super(new DocumentLineList(document)); + this.document = document; + } + + public IDocument getDocument() { + return document; + } + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/TMModelManager.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/TMModelManager.java index f04e11af2..37ab3b321 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/TMModelManager.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/TMModelManager.java @@ -1,57 +1,57 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.model; - -import java.util.HashMap; -import java.util.Map; - -import org.eclipse.jface.text.IDocument; -import org.eclipse.tm4e.core.model.ITMModel; -import org.eclipse.tm4e.ui.model.ITMModelManager; - -/** - * TextMate model manager which connect/disconnect a TextModel model - * {@link ITMModel} with an Eclipse {@link IDocument}. - */ -public class TMModelManager implements ITMModelManager { - - private static final ITMModelManager INSTANCE = new TMModelManager(); - - public static ITMModelManager getInstance() { - return INSTANCE; - } - - private final Map models; - - private TMModelManager() { - models = new HashMap<>(); - } - - @Override - public ITMModel connect(IDocument document) { - ITMModel model = models.get(document); - if (model != null) { - return model; - } - model = new TMDocumentModel(document); - models.put(document, model); - return model; - } - - @Override - public void disconnect(IDocument document) { - ITMModel model = models.remove(document); - if (model != null) { - model.dispose(); - } - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.model; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.text.IDocument; +import org.eclipse.tm4e.core.model.ITMModel; +import org.eclipse.tm4e.ui.model.ITMModelManager; + +/** + * TextMate model manager which connect/disconnect a TextModel model + * {@link ITMModel} with an Eclipse {@link IDocument}. + */ +public final class TMModelManager implements ITMModelManager { + + private static final ITMModelManager INSTANCE = new TMModelManager(); + + public static ITMModelManager getInstance() { + return INSTANCE; + } + + private final Map models = new HashMap<>(); + + private TMModelManager() { + } + + @Override + public ITMModel connect(final IDocument document) { + ITMModel model = models.get(document); + if (model != null) { + return model; + } + model = new TMDocumentModel(document); + models.put(document, model); + return model; + } + + @Override + public void disconnect(final IDocument document) { + final ITMModel model = models.remove(document); + if (model != null) { + model.dispose(); + } + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/package-info.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/package-info.java new file mode 100644 index 000000000..848fee081 --- /dev/null +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/model/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.ui.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/package-info.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/package-info.java new file mode 100644 index 000000000..2e9e022ab --- /dev/null +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.ui.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/GrammarPreferencePage.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/GrammarPreferencePage.java index a1a1a1412..7bde5db46 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/GrammarPreferencePage.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/GrammarPreferencePage.java @@ -6,14 +6,19 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM Corporation - initial API and implementation - * Nicolaj Hoess - Editor templates pref page: Allow to sort by column - https://bugs.eclipse.org/203722 - * Angelo Zerr - Adapt org.eclipse.ui.texteditor.templates.TemplatePreferencePage for TextMate grammar + * IBM Corporation - initial API and implementation + * Nicolaj Hoess - Editor templates pref page: Allow to sort by column - + * https://bugs.eclipse.org/203722 + * Angelo Zerr - Adapt org.eclipse.ui.texteditor.templates.TemplatePreferencePage for TextMate + * grammar *******************************************************************************/ package org.eclipse.tm4e.ui.internal.preferences; +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + import java.util.Arrays; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.jface.preference.PreferencePage; @@ -72,98 +77,100 @@ * provides controls for adding, removing and changing grammar as well as * enablement, default management. */ -public class GrammarPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { +public final class GrammarPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { - public final static String PAGE_ID = "org.eclipse.tm4e.ui.preferences.GrammarPreferencePage"; + static final String PAGE_ID = "org.eclipse.tm4e.ui.preferences.GrammarPreferencePage"; // Managers - private IGrammarRegistryManager grammarRegistryManager; - private IThemeManager themeManager; - private ISnippetManager snippetManager; + private IGrammarRegistryManager grammarRegistryManager = new WorkingCopyGrammarRegistryManager( + TMEclipseRegistryPlugin.getGrammarRegistryManager()); + private IThemeManager themeManager = new WorkingCopyThemeManager(TMUIPlugin.getThemeManager()); + private ISnippetManager snippetManager = TMUIPlugin.getSnippetManager(); // Grammar list + @Nullable private TableViewer grammarViewer; - private Button grammarNewButton; + + @Nullable private Button grammarRemoveButton; // General tab + @Nullable private GrammarInfoWidget grammarInfoWidget; // Content type tab + @Nullable private ContentTypesBindingWidget contentTypesWidget; // Theme associations tab + @Nullable private ThemeAssociationsWidget themeAssociationsWidget; // Preview + @Nullable private TMViewer previewViewer; public GrammarPreferencePage() { - super(); setDescription(TMUIMessages.GrammarPreferencePage_description); - setGrammarRegistryManager( - new WorkingCopyGrammarRegistryManager(TMEclipseRegistryPlugin.getGrammarRegistryManager())); - setThemeManager(new WorkingCopyThemeManager(TMUIPlugin.getThemeManager())); - setSnippetManager(TMUIPlugin.getSnippetManager()); } /** * Returns the grammar registry manager. - * + * * @return the grammar registry manager. */ - public IGrammarRegistryManager getGrammarRegistryManager() { + IGrammarRegistryManager getGrammarRegistryManager() { return grammarRegistryManager; } /** * Set the grammar registry manager. - * + * * @param grammarRegistryManager */ - public void setGrammarRegistryManager(IGrammarRegistryManager grammarRegistryManager) { + void setGrammarRegistryManager(final IGrammarRegistryManager grammarRegistryManager) { this.grammarRegistryManager = grammarRegistryManager; } /** * Returns the theme manager. - * + * * @return the theme manager. */ - public IThemeManager getThemeManager() { + IThemeManager getThemeManager() { return themeManager; } /** * Set the theme manager. - * + * * @param themeManager */ - public void setThemeManager(IThemeManager themeManager) { + void setThemeManager(final IThemeManager themeManager) { this.themeManager = themeManager; } - public ISnippetManager getSnippetManager() { + ISnippetManager getSnippetManager() { return snippetManager; } - public void setSnippetManager(ISnippetManager snippetManager) { + void setSnippetManager(final ISnippetManager snippetManager) { this.snippetManager = snippetManager; } @Override - protected Control createContents(Composite ancestor) { - Composite parent = new Composite(ancestor, SWT.NONE); - GridLayout layout = new GridLayout(); + protected Control createContents(@Nullable final Composite ancestor) { + final var parent = new Composite(ancestor, SWT.NONE); + final var layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; layout.marginWidth = 0; parent.setLayout(layout); - Composite innerParent = new Composite(parent, SWT.NONE); - GridLayout innerLayout = new GridLayout(); + final var innerParent = new Composite(parent, SWT.NONE); + final var innerLayout = new GridLayout(); innerLayout.numColumns = 2; innerLayout.marginHeight = 0; innerLayout.marginWidth = 0; innerParent.setLayout(innerLayout); - GridData gd = new GridData(GridData.FILL_BOTH); + final var gd = new GridData(GridData.FILL_BOTH); gd.horizontalSpan = 2; innerParent.setLayoutData(gd); @@ -171,7 +178,7 @@ protected Control createContents(Composite ancestor) { createGrammarDetailContent(innerParent); previewViewer = doCreateViewer(innerParent); - grammarViewer.setInput(grammarRegistryManager); + castNonNull(grammarViewer).setInput(grammarRegistryManager); updateButtons(); Dialog.applyDialogFont(parent); @@ -182,44 +189,42 @@ protected Control createContents(Composite ancestor) { /** * Create grammar list content. - * - * @param parent */ - private void createGrammarListContent(Composite parent) { - Composite tableComposite = new Composite(parent, SWT.NONE); - GridData data = new GridData(GridData.FILL_BOTH); + private void createGrammarListContent(final Composite parent) { + final var tableComposite = new Composite(parent, SWT.NONE); + final var data = new GridData(GridData.FILL_BOTH); data.widthHint = 360; data.heightHint = convertHeightInCharsToPixels(10); tableComposite.setLayoutData(data); - TableColumnLayout columnLayout = new TableColumnLayout(); + final var columnLayout = new TableColumnLayout(); tableComposite.setLayout(columnLayout); - Table table = new Table(tableComposite, + final var table = new Table(tableComposite, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE); table.setHeaderVisible(true); table.setLinesVisible(true); - GC gc = new GC(getShell()); + final GC gc = new GC(getShell()); gc.setFont(JFaceResources.getDialogFont()); - ColumnViewerComparator viewerComparator = new ColumnViewerComparator(); + final var viewerComparator = new ColumnViewerComparator(); - grammarViewer = new TableViewer(table); + final var grammarViewer = this.grammarViewer = new TableViewer(table); - TableColumn column1 = new TableColumn(table, SWT.NONE); + final var column1 = new TableColumn(table, SWT.NONE); column1.setText(TMUIMessages.GrammarPreferencePage_column_scopeName); int minWidth = computeMinimumColumnWidth(gc, TMUIMessages.GrammarPreferencePage_column_scopeName); columnLayout.setColumnData(column1, new ColumnWeightData(2, minWidth, true)); column1.addSelectionListener(new ColumnSelectionAdapter(column1, grammarViewer, 0, viewerComparator)); - TableColumn column2 = new TableColumn(table, SWT.NONE); + final var column2 = new TableColumn(table, SWT.NONE); column2.setText(TMUIMessages.GrammarPreferencePage_column_path); minWidth = computeMinimumColumnWidth(gc, TMUIMessages.GrammarPreferencePage_column_path); columnLayout.setColumnData(column2, new ColumnWeightData(2, minWidth, true)); column2.addSelectionListener(new ColumnSelectionAdapter(column2, grammarViewer, 1, viewerComparator)); - TableColumn column3 = new TableColumn(table, SWT.NONE); + final var column3 = new TableColumn(table, SWT.NONE); column3.setText(TMUIMessages.GrammarPreferencePage_column_pluginId); minWidth = computeMinimumColumnWidth(gc, TMUIMessages.GrammarPreferencePage_column_pluginId); columnLayout.setColumnData(column3, new ColumnWeightData(2, minWidth, true)); @@ -230,58 +235,62 @@ private void createGrammarListContent(Composite parent) { grammarViewer.setLabelProvider(new GrammarDefinitionLabelProvider()); grammarViewer.setContentProvider(new GrammarDefinitionContentProvider()); grammarViewer.setComparator(viewerComparator); - grammarViewer.addSelectionChangedListener(new ISelectionChangedListener() { - @Override - public void selectionChanged(SelectionChangedEvent e) { - IStructuredSelection selection = grammarViewer.getStructuredSelection(); + public void selectionChanged(@Nullable final SelectionChangedEvent e) { + if (e == null) + return; + final IStructuredSelection selection = grammarViewer.getStructuredSelection(); if (selection.isEmpty()) { return; } - IGrammarDefinition definition = (IGrammarDefinition) (selection).getFirstElement(); + final IGrammarDefinition definition = (IGrammarDefinition) (selection).getFirstElement(); + // Update button - grammarRemoveButton.setEnabled(definition.getPluginId() == null); - themeAssociationsWidget.getNewButton().setEnabled(false); - themeAssociationsWidget.getRemoveButton().setEnabled(false); + castNonNull(grammarRemoveButton).setEnabled(definition.getPluginId() == null); + castNonNull(themeAssociationsWidget).getNewButton().setEnabled(false); + castNonNull(themeAssociationsWidget).getRemoveButton().setEnabled(false); + // Select grammar selectGrammar(definition); } - private void selectGrammar(IGrammarDefinition definition) { - String scopeName = definition.getScopeName(); + private void selectGrammar(final IGrammarDefinition definition) { + final String scopeName = definition.getScopeName(); // Fill "General" tab fillGeneralTab(scopeName); // Fill "Content type" tab fillContentTypeTab(scopeName); // Fill "Theme" tab - IThemeAssociation selectedAssociation = fillThemeTab(definition); + final IThemeAssociation selectedAssociation = fillThemeTab(definition); // Fill preview fillPreview(scopeName, selectedAssociation); } - private void fillGeneralTab(String scopeName) { - IGrammar grammar = grammarRegistryManager.getGrammarForScope(scopeName); - grammarInfoWidget.refresh(grammar); + private void fillGeneralTab(final String scopeName) { + final IGrammar grammar = grammarRegistryManager.getGrammarForScope(scopeName); + castNonNull(grammarInfoWidget).refresh(grammar); } - private void fillContentTypeTab(String scopeName) { + private void fillContentTypeTab(final String scopeName) { // Load the content type binding for the given grammar - contentTypesWidget.setInput(grammarRegistryManager.getContentTypesForScope(scopeName)); + castNonNull(contentTypesWidget).setInput(grammarRegistryManager.getContentTypesForScope(scopeName)); } - private IThemeAssociation fillThemeTab(IGrammarDefinition definition) { + @Nullable + private IThemeAssociation fillThemeTab(final IGrammarDefinition definition) { IThemeAssociation selectedAssociation = null; - IStructuredSelection oldSelection = themeAssociationsWidget.getSelection(); + final var themeAssociationsWidget = castNonNull(GrammarPreferencePage.this.themeAssociationsWidget); + final IStructuredSelection oldSelection = themeAssociationsWidget.getSelection(); // Load the theme associations for the given grammar - IThemeAssociation[] themeAssociations = themeAssociationsWidget.setGrammarDefinition(definition); + final IThemeAssociation[] themeAssociations = themeAssociationsWidget.setGrammarDefinition(definition); // Try to keep selection if (!oldSelection.isEmpty() && Arrays.asList(themeAssociations).contains(oldSelection.getFirstElement())) { selectedAssociation = (IThemeAssociation) oldSelection.getFirstElement(); themeAssociationsWidget.setSelection(oldSelection); } else { - selectedAssociation = themeAssociations != null && themeAssociations.length > 0 + selectedAssociation = themeAssociations.length > 0 ? themeAssociations[0] : null; if (selectedAssociation != null) { @@ -291,22 +300,24 @@ private IThemeAssociation fillThemeTab(IGrammarDefinition definition) { return selectedAssociation; } - private void fillPreview(String scopeName, IThemeAssociation selectedAssociation) { + private void fillPreview(final String scopeName, @Nullable final IThemeAssociation selectedAssociation) { // Preview the grammar - IGrammar grammar = grammarRegistryManager.getGrammarForScope(scopeName); + final IGrammar grammar = grammarRegistryManager.getGrammarForScope(scopeName); if (selectedAssociation != null) { setPreviewTheme(selectedAssociation.getThemeId()); } + final var previewViewer = castNonNull(GrammarPreferencePage.this.previewViewer); previewViewer.setGrammar(grammar); // Snippet - ISnippet[] snippets = snippetManager.getSnippets(scopeName); - if (snippets != null && snippets.length > 0) { + final ISnippet[] snippets = snippetManager.getSnippets(scopeName); + if (snippets.length == 0) { + previewViewer.setText(""); + } else { // TODO: manage list of snippet for the given scope. - previewViewer.setText(snippets[0].getContent()); + previewViewer.setText(snippets[0].getContent()); } } - }); // Specify default sorting @@ -315,66 +326,64 @@ private void fillPreview(String scopeName, IThemeAssociation selectedAssociation BidiUtils.applyTextDirection(grammarViewer.getControl(), BidiUtils.BTD_DEFAULT); - Composite buttons = new Composite(parent, SWT.NONE); + final var buttons = new Composite(parent, SWT.NONE); buttons.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); - GridLayout layout = new GridLayout(); + final var layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; buttons.setLayout(layout); - grammarNewButton = new Button(buttons, SWT.PUSH); + final var grammarNewButton = new Button(buttons, SWT.PUSH); grammarNewButton.setText(TMUIMessages.Button_new); grammarNewButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); grammarNewButton.addListener(SWT.Selection, new Listener() { @Override - public void handleEvent(Event e) { + public void handleEvent(@Nullable final Event e) { add(); } private void add() { // Open import wizard for TextMate grammar. - TextMateGrammarImportWizard wizard = new TextMateGrammarImportWizard(false); + final var wizard = new TextMateGrammarImportWizard(false); wizard.setGrammarRegistryManager(grammarRegistryManager); - WizardDialog dialog = new WizardDialog(getShell(), wizard); + final var dialog = new WizardDialog(getShell(), wizard); if (dialog.open() == Window.OK) { // User grammar was saved, refresh the list of grammar and // select the created grammar. - IGrammarDefinition created = wizard.getCreatedDefinition(); + final IGrammarDefinition created = wizard.getCreatedDefinition(); grammarViewer.refresh(); grammarViewer.setSelection(new StructuredSelection(created)); } } }); - grammarRemoveButton = new Button(buttons, SWT.PUSH); + final var grammarRemoveButton = this.grammarRemoveButton = new Button(buttons, SWT.PUSH); grammarRemoveButton.setText(TMUIMessages.Button_remove); grammarRemoveButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); grammarRemoveButton.addListener(SWT.Selection, new Listener() { @Override - public void handleEvent(Event e) { + public void handleEvent(@Nullable final Event e) { remove(); } private void remove() { - IGrammarDefinition definition = (IGrammarDefinition) ((IStructuredSelection) grammarViewer.getSelection()).getFirstElement(); - grammarRegistryManager.unregisterGrammarDefinition(definition); - grammarViewer.refresh(); + final var definition = (IGrammarDefinition) ((IStructuredSelection) grammarViewer + .getSelection()).getFirstElement(); + grammarRegistryManager.unregisterGrammarDefinition(definition); + grammarViewer.refresh(); } }); } /** - * Create detail grammar content which is filled when a grammar is selected in - * the grammar list. - * - * @param parent + * Create detail grammar content which is filled when a grammar is selected in the grammar list. */ - private void createGrammarDetailContent(Composite parent) { - TabFolder folder = new TabFolder(parent, SWT.NONE); + private void createGrammarDetailContent(final Composite parent) { + final var folder = new TabFolder(parent, SWT.NONE); - GridData gd = new GridData(GridData.FILL_HORIZONTAL); + final var gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = 2; folder.setLayoutData(gd); @@ -386,14 +395,12 @@ private void createGrammarDetailContent(Composite parent) { /** * Create "General" tab - * - * @param folder */ - private void createGeneralTab(TabFolder folder) { - TabItem tab = new TabItem(folder, SWT.NONE); + private void createGeneralTab(final TabFolder folder) { + final var tab = new TabItem(folder, SWT.NONE); tab.setText(TMUIMessages.GrammarPreferencePage_tab_general_text); - Composite parent = new Composite(folder, SWT.NONE); + final var parent = new Composite(folder, SWT.NONE); parent.setLayout(new GridLayout()); parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); @@ -401,19 +408,16 @@ private void createGeneralTab(TabFolder folder) { grammarInfoWidget.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); tab.setControl(parent); - } /** * Create "Content type" tab - * - * @param folder */ - private void createContentTypeTab(TabFolder folder) { - TabItem tab = new TabItem(folder, SWT.NONE); + private void createContentTypeTab(final TabFolder folder) { + final var tab = new TabItem(folder, SWT.NONE); tab.setText(TMUIMessages.GrammarPreferencePage_tab_contentType_text); - Composite parent = new Composite(folder, SWT.NONE); + final var parent = new Composite(folder, SWT.NONE); parent.setLayout(new GridLayout()); parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); @@ -425,31 +429,31 @@ private void createContentTypeTab(TabFolder folder) { /** * Create "Theme" tab - * - * @param folder */ - private void createThemeTab(TabFolder folder) { - TabItem tab = new TabItem(folder, SWT.NONE); + private void createThemeTab(final TabFolder folder) { + final var tab = new TabItem(folder, SWT.NONE); tab.setText(TMUIMessages.GrammarPreferencePage_tab_theme_text); - Composite parent = new Composite(folder, SWT.NONE); + final var parent = new Composite(folder, SWT.NONE); parent.setLayout(new GridLayout()); parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - themeAssociationsWidget = new ThemeAssociationsWidget(themeManager, parent, SWT.NONE); - GridData data = new GridData(GridData.FILL_HORIZONTAL); + final var themeAssociationsWidget = this.themeAssociationsWidget = new ThemeAssociationsWidget(themeManager, + parent, SWT.NONE); + final var data = new GridData(GridData.FILL_HORIZONTAL); data.horizontalSpan = 2; themeAssociationsWidget.setLayoutData(data); themeAssociationsWidget.addSelectionChangedListener(new ISelectionChangedListener() { @Override - public void selectionChanged(SelectionChangedEvent e) { - IThemeAssociation association = (IThemeAssociation) ((IStructuredSelection) e.getSelection()) - .getFirstElement(); + public void selectionChanged(@Nullable final SelectionChangedEvent e) { + if (e == null) + return; + final var association = (IThemeAssociation) ((IStructuredSelection) e.getSelection()).getFirstElement(); selectTheme(association); } - private void selectTheme(IThemeAssociation association) { + private void selectTheme(@Nullable final IThemeAssociation association) { themeAssociationsWidget.getNewButton() .setEnabled(association != null /* && association.getPluginId() == null */); themeAssociationsWidget.getRemoveButton() @@ -463,23 +467,23 @@ private void selectTheme(IThemeAssociation association) { tab.setControl(parent); } - private void setPreviewTheme(String themeId) { - ITheme theme = themeManager.getThemeById(themeId); - if (theme != null) { + private void setPreviewTheme(final String themeId) { + final ITheme theme = themeManager.getThemeById(themeId); + if (theme != null && previewViewer != null) { previewViewer.setTheme(theme); } } /** * Create "Injection" tab - * + * * @param folder */ - private void createInjectionTab(TabFolder folder) { - TabItem tab = new TabItem(folder, SWT.NONE); + private void createInjectionTab(final TabFolder folder) { + final var tab = new TabItem(folder, SWT.NONE); tab.setText(TMUIMessages.GrammarPreferencePage_tab_injection_text); - Composite parent = new Composite(folder, SWT.NONE); + final var parent = new Composite(folder, SWT.NONE); parent.setLayout(new GridLayout()); parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); @@ -488,42 +492,42 @@ private void createInjectionTab(TabFolder folder) { tab.setControl(parent); } - private int computeMinimumColumnWidth(GC gc, String string) { - return gc.stringExtent(string).x + 10; // pad 10 to accommodate table - // header trimmings + private int computeMinimumColumnWidth(final GC gc, final String string) { + return gc.stringExtent(string).x + 10; // pad 10 to accommodate table header trimmings } private void updateButtons() { - grammarRemoveButton.setEnabled(false); + if (grammarRemoveButton != null) + grammarRemoveButton.setEnabled(false); } @Override - public void setVisible(boolean visible) { + public void setVisible(final boolean visible) { super.setVisible(visible); if (visible) setTitle(TMUIMessages.GrammarPreferencePage_title); } @Override - public void init(IWorkbench workbench) { + public void init(@Nullable final IWorkbench workbench) { } - private TMViewer doCreateViewer(Composite parent) { - Label label = new Label(parent, SWT.NONE); + private TMViewer doCreateViewer(final Composite parent) { + final var label = new Label(parent, SWT.NONE); label.setText(TMUIMessages.GrammarPreferencePage_preview); - GridData data = new GridData(); + var data = new GridData(); data.horizontalSpan = 2; label.setLayoutData(data); - TMViewer viewer = createViewer(parent); + final TMViewer viewer = createViewer(parent); // Don't set caret to 'null' as this causes // https://bugs.eclipse.org/293263 // viewer.getTextWidget().setCaret(null); - Control control = viewer.getControl(); + final var control = viewer.getControl(); data = new GridData(GridData.FILL_BOTH); data.horizontalSpan = 2; data.heightHint = convertHeightInCharsToPixels(5); @@ -538,10 +542,11 @@ private TMViewer doCreateViewer(Composite parent) { * source viewer featuring e.g. syntax coloring. * * @param parent - * the parent control + * the parent control + * * @return a configured source viewer */ - protected TMViewer createViewer(Composite parent) { + private TMViewer createViewer(final Composite parent) { return new TMViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); } @@ -551,8 +556,8 @@ public boolean performOk() { // Save the working copy if there are some changed. grammarRegistryManager.save(); themeManager.save(); - } catch (BackingStoreException e) { - e.printStackTrace(); + } catch (final BackingStoreException ex) { + ex.printStackTrace(); return false; } return super.performOk(); diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/PreferenceConstants.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/PreferenceConstants.java index 4afb63789..656cf9129 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/PreferenceConstants.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/PreferenceConstants.java @@ -1,28 +1,28 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.preferences; - -/** - * Preferences constants for theme. - * - */ -public class PreferenceConstants { - - public static final String THEMES = "org.eclipse.tm4e.ui.themes"; - - public static final String THEME_ASSOCIATIONS = "org.eclipse.tm4e.ui.themeAssociations"; - - public static final String E4_THEME_ID = "themeid"; //$NON-NLS-1$ - - public static final String EDITOR_CURRENTLINE_HIGHLIGHT = "currentLineColor"; //$NON-NLS-1$ - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.preferences; + +/** + * Preferences constants for theme. + * + */ +public final class PreferenceConstants { + + public static final String THEMES = "org.eclipse.tm4e.ui.themes"; + + public static final String THEME_ASSOCIATIONS = "org.eclipse.tm4e.ui.themeAssociations"; + + public static final String E4_THEME_ID = "themeid"; //$NON-NLS-1$ + + public static final String EDITOR_CURRENTLINE_HIGHLIGHT = "currentLineColor"; //$NON-NLS-1$ + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/PreferenceHelper.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/PreferenceHelper.java index 1ec96e32f..717e7b189 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/PreferenceHelper.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/PreferenceHelper.java @@ -1,48 +1,42 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.preferences; - -import java.lang.reflect.Type; -import java.util.Collection; - -import org.eclipse.tm4e.ui.themes.IThemeAssociation; -import org.eclipse.tm4e.ui.themes.ThemeAssociation; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.InstanceCreator; - -/** - * Helper class load, save theme preferences with Json format. - * - */ -public class PreferenceHelper { - - private static final Gson DEFAULT_GSON; - - static { - DEFAULT_GSON = new GsonBuilder().registerTypeAdapter(IThemeAssociation.class, new InstanceCreator() { - @Override - public ThemeAssociation createInstance(Type type) { - return new ThemeAssociation(); - } - }).create(); - } - - public static IThemeAssociation[] loadThemeAssociations(String json) { - return DEFAULT_GSON.fromJson(json, ThemeAssociation[].class); - } - - public static String toJsonThemeAssociations(Collection themeAssociations) { - return DEFAULT_GSON.toJson(themeAssociations); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.preferences; + +import java.util.Collection; + +import org.eclipse.tm4e.ui.themes.IThemeAssociation; +import org.eclipse.tm4e.ui.themes.ThemeAssociation; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.InstanceCreator; + +/** + * Helper class load, save theme preferences with Json format. + * + */ +public final class PreferenceHelper { + + private static final Gson DEFAULT_GSON; + + static { + DEFAULT_GSON = new GsonBuilder().registerTypeAdapter(IThemeAssociation.class, (InstanceCreator) type -> new ThemeAssociation()).create(); + } + + public static IThemeAssociation[] loadThemeAssociations(final String json) { + return DEFAULT_GSON.fromJson(json, ThemeAssociation[].class); + } + + public static String toJsonThemeAssociations(final Collection themeAssociations) { + return DEFAULT_GSON.toJson(themeAssociations); + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/TextMatePreferencePage.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/TextMatePreferencePage.java index c7024da96..b610c565e 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/TextMatePreferencePage.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/TextMatePreferencePage.java @@ -11,6 +11,7 @@ */ package org.eclipse.tm4e.ui.internal.preferences; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; @@ -27,16 +28,12 @@ * TextMate Global preferences page. * */ -public class TextMatePreferencePage extends PreferencePage implements IWorkbenchPreferencePage { - - public TextMatePreferencePage() { - - } +public final class TextMatePreferencePage extends PreferencePage implements IWorkbenchPreferencePage { @Override - protected Control createContents(Composite parent) { - Composite composite = new Composite(parent, SWT.NONE); - GridLayout layout = new GridLayout(1, false); + protected Control createContents(@Nullable final Composite parent) { + final Composite composite = new Composite(parent, SWT.NONE); + final GridLayout layout = new GridLayout(1, false); layout.marginHeight = layout.marginWidth = 0; composite.setLayout(layout); @@ -57,16 +54,16 @@ protected Control createContents(Composite parent) { } - private void addRelatedLink(Composite parent, String pageId, String message) { - PreferenceLinkArea contentTypeArea = new PreferenceLinkArea(parent, SWT.NONE, pageId, message, + private void addRelatedLink(final Composite parent, final String pageId, final String message) { + final PreferenceLinkArea contentTypeArea = new PreferenceLinkArea(parent, SWT.NONE, pageId, message, (IWorkbenchPreferenceContainer) getContainer(), null); - GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL); + final GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL); contentTypeArea.getControl().setLayoutData(data); } @Override - public void init(IWorkbench workbench) { + public void init(@Nullable final IWorkbench workbench) { } } diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/ThemePreferencePage.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/ThemePreferencePage.java index e685ede86..ed08ea885 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/ThemePreferencePage.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/ThemePreferencePage.java @@ -6,16 +6,20 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM Corporation - initial API and implementation - * Nicolaj Hoess - Editor templates pref page: Allow to sort by column - https://bugs.eclipse.org/203722 - * Angelo Zerr - Adapt org.eclipse.ui.texteditor.templates.TemplatePreferencePage for TextMate theme + * IBM Corporation - initial API and implementation + * Nicolaj Hoess - Editor templates pref page: Allow to sort by column - + * https://bugs.eclipse.org/203722 + * Angelo Zerr - Adapt org.eclipse.ui.texteditor.templates.TemplatePreferencePage for TextMate + * theme *******************************************************************************/ package org.eclipse.tm4e.ui.internal.preferences; +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; import java.io.File; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.jface.preference.PreferencePage; @@ -60,54 +64,57 @@ import org.osgi.service.prefs.BackingStoreException; /** - * A theme preference page allows configuration of the TextMate themes It - * provides controls for adding, removing and changing theme as well as - * enablement, default management. + * A theme preference page allows configuration of the TextMate themes. + * It provides controls for adding, removing and changing theme as well as enablement, default management. */ -public class ThemePreferencePage extends PreferencePage implements IWorkbenchPreferencePage { +public final class ThemePreferencePage extends PreferencePage implements IWorkbenchPreferencePage { - public final static String PAGE_ID = "org.eclipse.tm4e.ui.preferences.ThemePreferencePage"; + static final String PAGE_ID = "org.eclipse.tm4e.ui.preferences.ThemePreferencePage"; // Theme content + @Nullable private TableViewer themeViewer; + @Nullable private Button themeRemoveButton; // Preview content + @Nullable private ComboViewer grammarViewer; + @Nullable private TMViewer previewViewer; - private final IGrammarRegistryManager grammarRegistryManager; - private final IThemeManager themeManager; + private final IGrammarRegistryManager grammarRegistryManager = TMEclipseRegistryPlugin.getGrammarRegistryManager(); + private final IThemeManager themeManager = TMUIPlugin.getThemeManager(); + @Nullable private Button darkThemeButton; + @Nullable private Button defaultThemeButton; - + + @Nullable private ITheme selectedTheme; public ThemePreferencePage() { - super(); setDescription(TMUIMessages.ThemePreferencePage_description); - this.grammarRegistryManager = TMEclipseRegistryPlugin.getGrammarRegistryManager(); - this.themeManager = TMUIPlugin.getThemeManager(); } @Override - protected Control createContents(Composite ancestor) { - Composite parent = new Composite(ancestor, SWT.NONE); - GridLayout layout = new GridLayout(); + protected Control createContents(@Nullable final Composite ancestor) { + final Composite parent = new Composite(ancestor, SWT.NONE); + final GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; layout.marginWidth = 0; parent.setLayout(layout); - Composite innerParent = new Composite(parent, SWT.NONE); - GridLayout innerLayout = new GridLayout(); + final Composite innerParent = new Composite(parent, SWT.NONE); + final GridLayout innerLayout = new GridLayout(); innerLayout.numColumns = 2; innerLayout.marginHeight = 0; innerLayout.marginWidth = 0; innerParent.setLayout(innerLayout); - GridData gd = new GridData(GridData.FILL_BOTH); + final GridData gd = new GridData(GridData.FILL_BOTH); gd.horizontalSpan = 2; innerParent.setLayoutData(gd); @@ -115,11 +122,13 @@ protected Control createContents(Composite ancestor) { createThemeDetailContent(innerParent); createPreviewContent(innerParent); + final var grammarViewer = castNonNull(this.grammarViewer); grammarViewer.setInput(grammarRegistryManager); if (grammarViewer.getCombo().getItemCount() > 0) { grammarViewer.getCombo().select(0); } - themeViewer.setInput(themeManager); + + castNonNull(themeViewer).setInput(themeManager); Dialog.applyDialogFont(parent); innerParent.layout(); @@ -132,42 +141,42 @@ protected Control createContents(Composite ancestor) { * * @param parent */ - private void createThemesContent(Composite parent) { + private void createThemesContent(final Composite parent) { GridLayout layout; - Composite tableComposite = new Composite(parent, SWT.NONE); - GridData data = new GridData(GridData.FILL_BOTH); + final Composite tableComposite = new Composite(parent, SWT.NONE); + final GridData data = new GridData(GridData.FILL_BOTH); data.widthHint = 360; data.heightHint = convertHeightInCharsToPixels(10); tableComposite.setLayoutData(data); - TableColumnLayout columnLayout = new TableColumnLayout(); + final TableColumnLayout columnLayout = new TableColumnLayout(); tableComposite.setLayout(columnLayout); - Table table = new Table(tableComposite, + final Table table = new Table(tableComposite, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL); table.setHeaderVisible(true); table.setLinesVisible(true); - GC gc = new GC(getShell()); + final GC gc = new GC(getShell()); gc.setFont(JFaceResources.getDialogFont()); - ColumnViewerComparator viewerComparator = new ColumnViewerComparator(); + final ColumnViewerComparator viewerComparator = new ColumnViewerComparator(); - themeViewer = new TableViewer(table); + final var themeViewer = this.themeViewer = new TableViewer(table); - TableColumn column1 = new TableColumn(table, SWT.NONE); + final TableColumn column1 = new TableColumn(table, SWT.NONE); column1.setText(TMUIMessages.ThemePreferencePage_column_name); int minWidth = computeMinimumColumnWidth(gc, TMUIMessages.ThemePreferencePage_column_name); columnLayout.setColumnData(column1, new ColumnWeightData(2, minWidth, true)); column1.addSelectionListener(new ColumnSelectionAdapter(column1, themeViewer, 0, viewerComparator)); - TableColumn column2 = new TableColumn(table, SWT.NONE); + final TableColumn column2 = new TableColumn(table, SWT.NONE); column2.setText(TMUIMessages.ThemePreferencePage_column_path); minWidth = computeMinimumColumnWidth(gc, TMUIMessages.ThemePreferencePage_column_path); columnLayout.setColumnData(column2, new ColumnWeightData(2, minWidth, true)); column2.addSelectionListener(new ColumnSelectionAdapter(column2, themeViewer, 1, viewerComparator)); - TableColumn column3 = new TableColumn(table, SWT.NONE); + final TableColumn column3 = new TableColumn(table, SWT.NONE); column3.setText(TMUIMessages.ThemePreferencePage_column_pluginId); minWidth = computeMinimumColumnWidth(gc, TMUIMessages.ThemePreferencePage_column_pluginId); columnLayout.setColumnData(column3, new ColumnWeightData(2, minWidth, true)); @@ -180,11 +189,12 @@ private void createThemesContent(Composite parent) { themeViewer.setComparator(viewerComparator); themeViewer.addSelectionChangedListener(e -> { // Fill Theme details - selectedTheme = ((ITheme) ((IStructuredSelection) themeViewer.getSelection()).getFirstElement()); + final var selectedTheme = ThemePreferencePage.this.selectedTheme = ((ITheme) ((IStructuredSelection) themeViewer + .getSelection()).getFirstElement()); if (selectedTheme != null) { - darkThemeButton.setSelection(selectedTheme.isDark()); - defaultThemeButton.setSelection(selectedTheme.isDefault()); - themeRemoveButton.setEnabled(selectedTheme.getPluginId() == null); + castNonNull(darkThemeButton).setSelection(selectedTheme.isDark()); + castNonNull(defaultThemeButton).setSelection(selectedTheme.isDefault()); + castNonNull(themeRemoveButton).setEnabled(selectedTheme.getPluginId() == null); } preview(); }); @@ -195,20 +205,20 @@ private void createThemesContent(Composite parent) { BidiUtils.applyTextDirection(themeViewer.getControl(), BidiUtils.BTD_DEFAULT); - Composite buttons = new Composite(parent, SWT.NONE); + final Composite buttons = new Composite(parent, SWT.NONE); buttons.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; buttons.setLayout(layout); - Button themeNewButton = new Button(buttons, SWT.PUSH); + final Button themeNewButton = new Button(buttons, SWT.PUSH); themeNewButton.setText(TMUIMessages.Button_new); themeNewButton.setLayoutData(getButtonGridData(themeNewButton)); themeNewButton.addListener(SWT.Selection, new Listener() { @Override - public void handleEvent(Event e) { - ITheme newTheme = addTheme(); + public void handleEvent(@Nullable final Event e) { + final ITheme newTheme = addTheme(); if (newTheme != null) { themeManager.registerTheme(newTheme); selectedTheme = newTheme; @@ -217,25 +227,28 @@ public void handleEvent(Event e) { } } + @Nullable private ITheme addTheme() { - FileDialog dialog = new FileDialog(getShell()); + final FileDialog dialog = new FileDialog(getShell()); dialog.setText("Select textmate theme file"); - dialog.setFilterExtensions(new String[]{"*.css"}); - String res = dialog.open(); + dialog.setFilterExtensions(new String[] { "*.css" }); + final String res = dialog.open(); if (res == null) { return null; } - File file = new File(res); - String name = file.getName().substring(0, file.getName().length() - ".css".length()); + final File file = new File(res); + final String name = file.getName().substring(0, file.getName().length() - ".css".length()); return new Theme(name, file.getAbsolutePath(), name, false, false); } }); - themeRemoveButton = new Button(buttons, SWT.PUSH); + final var themeRemoveButton = this.themeRemoveButton = new Button(buttons, SWT.PUSH); themeRemoveButton.setText(TMUIMessages.Button_remove); themeRemoveButton.setLayoutData(getButtonGridData(themeRemoveButton)); themeRemoveButton.addListener(SWT.Selection, e -> { - themeManager.unregisterTheme(selectedTheme); + if (selectedTheme != null) { + themeManager.unregisterTheme(selectedTheme); + } themeViewer.refresh(); }); } @@ -245,24 +258,24 @@ private ITheme addTheme() { * * @param parent */ - private void createThemeDetailContent(Composite ancestor) { - Composite parent = new Composite(ancestor, SWT.NONE); - GridData data = new GridData(GridData.FILL_HORIZONTAL); + private void createThemeDetailContent(final Composite ancestor) { + final Composite parent = new Composite(ancestor, SWT.NONE); + final GridData data = new GridData(GridData.FILL_HORIZONTAL); data.horizontalSpan = 2; parent.setLayoutData(data); - GridLayout layout = new GridLayout(); + final GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.marginLeft = 0; layout.marginRight = 0; parent.setLayout(layout); - darkThemeButton = new Button(parent, SWT.CHECK); + final var darkThemeButton = this.darkThemeButton = new Button(parent, SWT.CHECK); darkThemeButton.setText(TMUIMessages.ThemePreferencePage_darkThemeButton_label); darkThemeButton.setEnabled(false); - defaultThemeButton = new Button(parent, SWT.CHECK); + final var defaultThemeButton = this.defaultThemeButton = new Button(parent, SWT.CHECK); defaultThemeButton.setText(TMUIMessages.ThemePreferencePage_defaultThemeButton_label); defaultThemeButton.setEnabled(false); } @@ -272,13 +285,13 @@ private void createThemeDetailContent(Composite ancestor) { * * @param parent */ - private void createPreviewContent(Composite ancestor) { - Composite parent = new Composite(ancestor, SWT.NONE); - GridData data = new GridData(GridData.FILL_HORIZONTAL); + private void createPreviewContent(final Composite ancestor) { + final Composite parent = new Composite(ancestor, SWT.NONE); + final GridData data = new GridData(GridData.FILL_HORIZONTAL); data.horizontalSpan = 2; parent.setLayoutData(data); - GridLayout layout = new GridLayout(2, false); + final GridLayout layout = new GridLayout(2, false); layout.marginHeight = 0; layout.marginWidth = 0; parent.setLayout(layout); @@ -286,20 +299,16 @@ private void createPreviewContent(Composite ancestor) { previewViewer = doCreateViewer(parent); } - private int computeMinimumColumnWidth(GC gc, String string) { + private int computeMinimumColumnWidth(final GC gc, final String string) { return gc.stringExtent(string).x + 10; // pad 10 to accommodate table - // header trimmings + // header trimmings } /** - * Return the grid data for the button. - * - * @param button - * the button - * @return the grid data + * @returns the grid data for the button. */ - private static GridData getButtonGridData(Button button) { - GridData data = new GridData(GridData.FILL_HORIZONTAL); + private static GridData getButtonGridData(final Button button) { + final GridData data = new GridData(GridData.FILL_HORIZONTAL); // TODO replace SWTUtil // data.widthHint= SWTUtil.getButtonWidthHint(button); // data.heightHint= SWTUtil.getButtonHeightHint(button); @@ -308,55 +317,56 @@ private static GridData getButtonGridData(Button button) { } @Override - public void setVisible(boolean visible) { + public void setVisible(final boolean visible) { super.setVisible(visible); if (visible) setTitle(TMUIMessages.ThemePreferencePage_title); } @Override - public void init(IWorkbench workbench) { + public void init(@Nullable final IWorkbench workbench) { } private void preview() { - IStructuredSelection selection = (IStructuredSelection) themeViewer.getSelection(); + IStructuredSelection selection = (IStructuredSelection) castNonNull(themeViewer).getSelection(); if (selection.isEmpty()) { return; } - ITheme theme = (ITheme) selection.getFirstElement(); + final ITheme theme = (ITheme) selection.getFirstElement(); - selection = (IStructuredSelection) grammarViewer.getSelection(); + selection = (IStructuredSelection) castNonNull(grammarViewer).getSelection(); if (selection.isEmpty()) { return; } - IGrammarDefinition definition = (IGrammarDefinition) selection.getFirstElement(); + final IGrammarDefinition definition = (IGrammarDefinition) selection.getFirstElement(); // Preview the grammar - IGrammar grammar = grammarRegistryManager.getGrammarForScope(definition.getScopeName()); + final IGrammar grammar = grammarRegistryManager.getGrammarForScope(definition.getScopeName()); + final var previewViewer = castNonNull(this.previewViewer); previewViewer.setTheme(theme); previewViewer.setGrammar(grammar); } - private TMViewer doCreateViewer(Composite parent) { - Label label = new Label(parent, SWT.NONE); + private TMViewer doCreateViewer(final Composite parent) { + final Label label = new Label(parent, SWT.NONE); label.setText(TMUIMessages.ThemePreferencePage_preview); GridData data = new GridData(); label.setLayoutData(data); - grammarViewer = new ComboViewer(parent); + final var grammarViewer = this.grammarViewer = new ComboViewer(parent); grammarViewer.setContentProvider(new GrammarDefinitionContentProvider()); grammarViewer.setLabelProvider(new GrammarDefinitionLabelProvider()); grammarViewer.addSelectionChangedListener(e -> preview()); grammarViewer.getControl().setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - TMViewer viewer = createViewer(parent); + final TMViewer viewer = createViewer(parent); // Don't set caret to 'null' as this causes // https://bugs.eclipse.org/293263 // viewer.getTextWidget().setCaret(null); - Control control = viewer.getControl(); + final Control control = viewer.getControl(); data = new GridData(GridData.FILL_BOTH); data.horizontalSpan = 2; data.heightHint = convertHeightInCharsToPixels(5); @@ -371,10 +381,11 @@ private TMViewer doCreateViewer(Composite parent) { * source viewer featuring e.g. syntax coloring. * * @param parent - * the parent control + * the parent control + * * @return a configured source viewer */ - protected TMViewer createViewer(Composite parent) { + private TMViewer createViewer(final Composite parent) { return new TMViewer(parent, null, null, false, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); } @@ -384,10 +395,9 @@ public boolean performOk() { themeManager.save(); grammarRegistryManager.save(); return true; - } catch (BackingStoreException e) { - TMUIPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); + } catch (final BackingStoreException e) { + TMUIPlugin.log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); return false; } } - } diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/package-info.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/package-info.java new file mode 100644 index 000000000..ce3d8cb28 --- /dev/null +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/preferences/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.ui.internal.preferences; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/snippets/Snippet.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/snippets/Snippet.java index 1068a4535..de45af9c4 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/snippets/Snippet.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/snippets/Snippet.java @@ -1,62 +1,64 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.snippets; - -import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.tm4e.registry.TMResource; -import org.eclipse.tm4e.registry.XMLConstants; -import org.eclipse.tm4e.ui.snippets.ISnippet; - -public class Snippet extends TMResource implements ISnippet { - - private String scopeName; - private String name; - - /** - * Constructor for user preferences (loaded from Json with Gson). - */ - public Snippet() { - super(); - } - - /** - * Constructor for extension point. - * - * @param element - */ - public Snippet(String scopeName, String path, String name) { - super(path); - this.scopeName = scopeName; - this.name = name; - } - - public Snippet(IConfigurationElement ce) { - super(ce); - this.scopeName = ce.getAttribute(XMLConstants.SCOPE_NAME_ATTR); - this.name = ce.getAttribute(XMLConstants.NAME_ATTR); - } - - @Override - public String getName() { - return name; - } - - @Override - public String getContent() { - return getResourceContent(); - } - - @Override - public String getScopeName() { - return scopeName; - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.snippets; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.tm4e.registry.TMResource; +import org.eclipse.tm4e.registry.XMLConstants; +import org.eclipse.tm4e.ui.snippets.ISnippet; + +final class Snippet extends TMResource implements ISnippet { + + private String scopeName; + private String name; + + /** + * Constructor for user preferences (loaded from Json with Gson). + */ + Snippet() { + scopeName = ""; + name = ""; + } + + /** + * Constructor for extension point. + * + * @param scopeName + */ + Snippet(final String scopeName, final String path, final String name) { + super(path); + this.scopeName = scopeName; + this.name = name; + } + + Snippet(final IConfigurationElement ce) { + super(ce); + this.scopeName = ce.getAttribute(XMLConstants.SCOPE_NAME_ATTR); + this.name = ce.getAttribute(XMLConstants.NAME_ATTR); + } + + @Override + public String getName() { + return name; + } + + @Override + public String getContent() { + final var content = getResourceContent(); + return content == null ? "":content; + } + + @Override + public String getScopeName() { + return scopeName; + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/snippets/SnippetManager.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/snippets/SnippetManager.java index 427ca9a89..bea1f614a 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/snippets/SnippetManager.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/snippets/SnippetManager.java @@ -9,84 +9,85 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.ui.internal.snippets; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.core.runtime.Platform; -import org.eclipse.tm4e.ui.TMUIPlugin; -import org.eclipse.tm4e.ui.snippets.ISnippet; -import org.eclipse.tm4e.ui.snippets.ISnippetManager; - -public class SnippetManager implements ISnippetManager { - - private static final ISnippet[] EMPTY_SNIPPETS = new ISnippet[0]; - - private static final String SNIPPET_ELT = "snippet"; - - // "snippets" extension point - private static final String EXTENSION_SNIPPETS = "snippets"; //$NON-NLS-1$ - - private static ISnippetManager INSTANCE; - - public static ISnippetManager getInstance() { - if (INSTANCE != null) { - return INSTANCE; - } - INSTANCE = createInstance(); - return INSTANCE; - } - - private static synchronized ISnippetManager createInstance() { - if (INSTANCE != null) { - return INSTANCE; - } - SnippetManager manager = new SnippetManager(); - manager.load(); - return manager; - } - - private final Map> snippets; - - public SnippetManager() { - this.snippets = new HashMap<>(); - } - - private void load() { - loadGrammarsFromExtensionPoints(); - } - - /** - * Load snippets from extension point. - */ - private void loadGrammarsFromExtensionPoints() { - IConfigurationElement[] cf = Platform.getExtensionRegistry().getConfigurationElementsFor(TMUIPlugin.PLUGIN_ID, - EXTENSION_SNIPPETS); - for (IConfigurationElement ce : cf) { - String extensionName = ce.getName(); - if (SNIPPET_ELT.equals(extensionName)) { - this.registerSnippet(new Snippet(ce)); - } - } - } - - private void registerSnippet(Snippet snippet) { - String scopeName = snippet.getScopeName(); - Collection snippets = this.snippets.get(scopeName); - if (snippets == null) { - snippets = new ArrayList<>(); - this.snippets.put(scopeName, snippets); - } - snippets.add(snippet); - } - - @Override - public ISnippet[] getSnippets(String scopeName) { - Collection snippets = this.snippets.get(scopeName); - return snippets != null ? snippets.toArray(new ISnippet[snippets.size()]) : EMPTY_SNIPPETS; - } -} +package org.eclipse.tm4e.ui.internal.snippets; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.ui.TMUIPlugin; +import org.eclipse.tm4e.ui.snippets.ISnippet; +import org.eclipse.tm4e.ui.snippets.ISnippetManager; + +public final class SnippetManager implements ISnippetManager { + + private static final ISnippet[] EMPTY_SNIPPETS = {}; + + private static final String SNIPPET_ELT = "snippet"; + + // "snippets" extension point + private static final String EXTENSION_SNIPPETS = "snippets"; //$NON-NLS-1$ + + @Nullable + private static ISnippetManager INSTANCE; + + public static ISnippetManager getInstance() { + if (INSTANCE != null) { + return INSTANCE; + } + INSTANCE = createInstance(); + return INSTANCE; + } + + private static synchronized ISnippetManager createInstance() { + if (INSTANCE != null) { + return INSTANCE; + } + final SnippetManager manager = new SnippetManager(); + manager.load(); + return manager; + } + + private final Map> snippets = new HashMap<>(); + + private SnippetManager() { + } + + private void load() { + loadGrammarsFromExtensionPoints(); + } + + /** + * Load snippets from extension point. + */ + private void loadGrammarsFromExtensionPoints() { + final IConfigurationElement[] cf = Platform.getExtensionRegistry().getConfigurationElementsFor(TMUIPlugin.PLUGIN_ID, + EXTENSION_SNIPPETS); + for (final IConfigurationElement ce : cf) { + final String extensionName = ce.getName(); + if (SNIPPET_ELT.equals(extensionName)) { + this.registerSnippet(new Snippet(ce)); + } + } + } + + private void registerSnippet(final Snippet snippet) { + final String scopeName = snippet.getScopeName(); + Collection snippets = this.snippets.get(scopeName); + if (snippets == null) { + snippets = new ArrayList<>(); + this.snippets.put(scopeName, snippets); + } + snippets.add(snippet); + } + + @Override + public ISnippet[] getSnippets(final String scopeName) { + final Collection snippets = this.snippets.get(scopeName); + return snippets != null ? snippets.toArray(ISnippet[]::new) : EMPTY_SNIPPETS; + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/snippets/package-info.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/snippets/package-info.java new file mode 100644 index 000000000..fc0f77865 --- /dev/null +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/snippets/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.ui.internal.snippets; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/text/TMPresentationReconcilerTestGenerator.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/text/TMPresentationReconcilerTestGenerator.java index b654f665a..0f233360e 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/text/TMPresentationReconcilerTestGenerator.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/text/TMPresentationReconcilerTestGenerator.java @@ -1,205 +1,207 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.text; - -import org.eclipse.jface.text.DocumentEvent; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IDocumentListener; -import org.eclipse.jface.text.ITextListener; -import org.eclipse.jface.text.ITextViewer; -import org.eclipse.jface.text.TextEvent; -import org.eclipse.jface.text.TextPresentation; -import org.eclipse.tm4e.ui.text.ITMPresentationReconcilerListener; - -public class TMPresentationReconcilerTestGenerator - implements ITMPresentationReconcilerListener, IDocumentListener, ITextListener { - - private ITextViewer viewer; - private IDocument document; - - private StringBuilder code = new StringBuilder(); - - /*private List commands; - - private class Command { - final String command; - StyleRange[] ranges; - Throwable error; - - public Command(String command) { - this.command = command; - } - }*/ - - public TMPresentationReconcilerTestGenerator() { - //this.commands = new ArrayList<>(); - } - - @Override - public void install(ITextViewer viewer, IDocument document) { - this.viewer = viewer; - this.document = document; - document.addDocumentListener(this); - viewer.addTextListener(this); - - write("package org.eclipse.tm4e.ui.text;", true); - write("", true); - - write("import org.eclipse.jface.text.Document;", true); - write("import org.eclipse.jface.text.IDocument;", true); - write("import org.eclipse.jface.text.TextViewer;", true); - write("import org.eclipse.swt.SWT;", true); - write("import org.eclipse.swt.widgets.Display;", true); - write("import org.eclipse.swt.widgets.Shell;", true); - write("import org.eclipse.tm4e.core.grammar.IGrammar;", true); - write("import org.eclipse.tm4e.core.registry.Registry;", true); - write("import org.eclipse.tm4e.ui.text.TMPresentationReconciler;", true); - write("import org.eclipse.tm4e.ui.themes.ITokenProvider;", true); - write("import org.eclipse.tm4e.ui.themes.css.CSSTokenProvider;", true); - write("import org.junit.Test;", true); - write("", true); - - write("public class TMPresentationReconcilerTest {", true); - write("", true); - - write("\t@Test", true); - write("\tpublic void colorize() throws Exception {", true); - write("", true); - write("\t\tDisplay display = new Display();", true); - write("\t\tShell shell = new Shell(display);", true); - write("\t\tTextViewer viewer = new TextViewer(shell, SWT.NONE);", true); - write("\t\tIDocument document = new Document();", true); - write("\t\tviewer.setDocument(document);", true); - write("\t\tdocument.set(\""); - write(toText(document.get())); - write("\");", true); - - // commands.add(new Command("document.set(...)")); - write("", true); - write("\t\tTMPresentationReconciler reconciler = new TMPresentationReconciler();", true); - write("\t\treconciler.setTokenProvider(getTokenProvider());", true); - write("\t\treconciler.setGrammar(getGrammar());", true); - write("\t\treconciler.install(viewer);", true); - write("", true); - - } - - public String toText(String text) { - StringBuilder newText = new StringBuilder(); - for (int i = 0; i < text.length(); i++) { - char c = text.charAt(i); - switch (c) { - case '\n': - newText.append("\\n"); - break; - case '\r': - newText.append("\\r"); - break; - case '"': - newText.append("\\\""); - break; - default: - newText.append(c); - } - } - return newText.toString(); - } - - @Override - public void uninstall() { - -// for (Command command : commands) { -// write(toString(command.ranges)); -// } -// - write("", true); - write("\t\twhile (!shell.isDisposed()) {", true); - write("\t\t}", true); - - write("\t}", true); - - write("\tprivate static ITokenProvider getTokenProvider() {", true); - write("\t\treturn new CSSTokenProvider(TMPresentationReconcilerTest.class.getResourceAsStream(\"Solarized-light.css\"));", - true); - write("\t}", true); - write("", true); - - write("\tprivate static IGrammar getGrammar() {", true); - write("\t\tRegistry registry = new Registry();", true); - write("\t\ttry {", true); - write("\t\tString grammar=\"YouGrammar.tmLanguage\";", true); - write("\t\t\treturn registry.loadGrammarFromPathSync(grammar,TMPresentationReconcilerTest.class.getResourceAsStream(grammar));", - true); - write("\t\t} catch (Exception e) {", true); - write("\t\t\te.printStackTrace();", true); - write("\t\treturn null;", true); - write("\t\t}", true); - write("\t}", true); - - write("}"); - - System.err.println(code.toString()); - document.removeDocumentListener(this); - viewer.removeTextListener(this); - //commands.clear(); - - } - - @Override - public void colorize(TextPresentation presentation, Throwable e) { -// Command command = commands.get(commands.size() - 1); -// if (e != null) { -// command.error = e; -// } else { -// command.ranges = viewer.getTextWidget().getStyleRanges(); -// } - } - - private void write(String s, boolean newLine) { - code.append(s); - if (newLine) { - code.append("\n"); - } - } - - private void write(String s) { - write(s, false); - } - - @Override - public void documentAboutToBeChanged(DocumentEvent event) { - - } - - @Override - public void documentChanged(DocumentEvent event) { - - String command = "document.replace(" + event.getOffset() + ", " + event.getLength() + ", \"" - + toText(event.getText()) + "\");"; - write("\t\t" + command, true); - - //commands.add(new Command(command)); - } - - @Override - public void textChanged(TextEvent event) { - if (event.getDocumentEvent() != null) { - return; - } - - String command = "viewer.invalidateTextPresentation(" + event.getOffset() + ", " + event.getLength() + ");"; - write("\t\t" + command, true); - - //commands.add(new Command(command)); - - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.text; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentListener; +import org.eclipse.jface.text.ITextListener; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.TextEvent; +import org.eclipse.jface.text.TextPresentation; +import org.eclipse.tm4e.ui.text.ITMPresentationReconcilerListener; + +public final class TMPresentationReconcilerTestGenerator + implements ITMPresentationReconcilerListener, IDocumentListener, ITextListener { + + @Nullable + private ITextViewer viewer; + + @Nullable + private IDocument document; + + private final StringBuilder code = new StringBuilder(); + + /*private List commands = new ArrayList<>(); + + private static final class Command { + final String command; + StyleRange[] ranges; + Throwable error; + + Command(String command) { + this.command = command; + } + }*/ + + @Override + public void install(final ITextViewer viewer, final IDocument document) { + this.viewer = viewer; + this.document = document; + document.addDocumentListener(this); + viewer.addTextListener(this); + + write("package org.eclipse.tm4e.ui.text;", true); + write("", true); + + write("import org.eclipse.jface.text.Document;", true); + write("import org.eclipse.jface.text.IDocument;", true); + write("import org.eclipse.jface.text.TextViewer;", true); + write("import org.eclipse.swt.SWT;", true); + write("import org.eclipse.swt.widgets.Display;", true); + write("import org.eclipse.swt.widgets.Shell;", true); + write("import org.eclipse.tm4e.core.grammar.IGrammar;", true); + write("import org.eclipse.tm4e.core.registry.Registry;", true); + write("import org.eclipse.tm4e.ui.text.TMPresentationReconciler;", true); + write("import org.eclipse.tm4e.ui.themes.ITokenProvider;", true); + write("import org.eclipse.tm4e.ui.themes.css.CSSTokenProvider;", true); + write("import org.junit.Test;", true); + write("", true); + + write("public class TMPresentationReconcilerTest {", true); + write("", true); + + write("\t@Test", true); + write("\tpublic void colorize() throws Exception {", true); + write("", true); + write("\t\tDisplay display = new Display();", true); + write("\t\tShell shell = new Shell(display);", true); + write("\t\tTextViewer viewer = new TextViewer(shell, SWT.NONE);", true); + write("\t\tIDocument document = new Document();", true); + write("\t\tviewer.setDocument(document);", true); + write("\t\tdocument.set(\""); + write(toText(document.get())); + write("\");", true); + + // commands.add(new Command("document.set(...)")); + write("", true); + write("\t\tTMPresentationReconciler reconciler = new TMPresentationReconciler();", true); + write("\t\treconciler.setTokenProvider(getTokenProvider());", true); + write("\t\treconciler.setGrammar(getGrammar());", true); + write("\t\treconciler.install(viewer);", true); + write("", true); + + } + + private String toText(final String text) { + final StringBuilder newText = new StringBuilder(); + for (int i = 0; i < text.length(); i++) { + final char c = text.charAt(i); + switch (c) { + case '\n': + newText.append("\\n"); + break; + case '\r': + newText.append("\\r"); + break; + case '"': + newText.append("\\\""); + break; + default: + newText.append(c); + } + } + return newText.toString(); + } + + @Override + public void uninstall() { + + // for (Command command : commands) { + // write(toString(command.ranges)); + // } + // + write("", true); + write("\t\twhile (!shell.isDisposed()) {", true); + write("\t\t}", true); + + write("\t}", true); + + write("\tprivate static ITokenProvider getTokenProvider() {", true); + write("\t\treturn new CSSTokenProvider(TMPresentationReconcilerTest.class.getResourceAsStream(\"Solarized-light.css\"));", + true); + write("\t}", true); + write("", true); + + write("\tprivate static IGrammar getGrammar() {", true); + write("\t\tRegistry registry = new Registry();", true); + write("\t\ttry {", true); + write("\t\tString grammar=\"YouGrammar.tmLanguage\";", true); + write("\t\t\treturn registry.loadGrammarFromPathSync(grammar,TMPresentationReconcilerTest.class.getResourceAsStream(grammar));", + true); + write("\t\t} catch (Exception e) {", true); + write("\t\t\te.printStackTrace();", true); + write("\t\treturn null;", true); + write("\t\t}", true); + write("\t}", true); + + write("}"); + + System.err.println(code.toString()); + castNonNull(document).removeDocumentListener(this); + castNonNull(viewer).removeTextListener(this); + // commands.clear(); + } + + @Override + public void colorize(final TextPresentation presentation, @Nullable final Throwable e) { + // Command command = commands.get(commands.size() - 1); + // if (e != null) { + // command.error = e; + // } else { + // command.ranges = viewer.getTextWidget().getStyleRanges(); + // } + } + + private void write(final String s, final boolean newLine) { + code.append(s); + if (newLine) { + code.append("\n"); + } + } + + private void write(final String s) { + write(s, false); + } + + @Override + public void documentAboutToBeChanged(@Nullable final DocumentEvent event) { + + } + + @Override + public void documentChanged(@Nullable final DocumentEvent event) { + if (event == null) + return; + final String command = "document.replace(" + event.getOffset() + ", " + event.getLength() + ", \"" + + toText(event.getText()) + "\");"; + write("\t\t" + command, true); + + // commands.add(new Command(command)); + } + + @Override + public void textChanged(@Nullable final TextEvent event) { + if (event == null || event.getDocumentEvent() != null) { + return; + } + + final String command = "viewer.invalidateTextPresentation(" + event.getOffset() + ", " + event.getLength() + + ");"; + write("\t\t" + command, true); + + // commands.add(new Command(command)); + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/text/package-info.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/text/package-info.java new file mode 100644 index 000000000..220ced993 --- /dev/null +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/text/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.ui.internal.text; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/AbstractThemeManager.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/AbstractThemeManager.java index 43c68e4e0..9f0d93645 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/AbstractThemeManager.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/AbstractThemeManager.java @@ -1,149 +1,148 @@ -/** - * Copyright (c) 2015, 2021 Angelo ZERR and others. +/** + * Copyright (c) 2015, 2021 Angelo ZERR and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.themes; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.eclipse.swt.graphics.RGB; -import org.eclipse.tm4e.ui.themes.ITheme; -import org.eclipse.tm4e.ui.themes.IThemeAssociation; -import org.eclipse.tm4e.ui.themes.IThemeManager; -import org.eclipse.tm4e.ui.themes.ITokenProvider; -import org.eclipse.tm4e.ui.themes.ThemeAssociation; -import org.eclipse.tm4e.ui.utils.PreferenceUtils; - -/** - * TextMate theme manager implementation. - * - */ -public abstract class AbstractThemeManager implements IThemeManager { - - private final Map themes; - private final ThemeAssociationRegistry themeAssociationRegistry; - - public AbstractThemeManager() { - this.themes = new LinkedHashMap<>(); - this.themeAssociationRegistry = new ThemeAssociationRegistry(); - } - - @Override - public void registerTheme(ITheme theme) { - themes.put(theme.getId(), theme); - } - - @Override - public void unregisterTheme(ITheme theme) { - themes.remove(theme.getId()); - } - - @Override - public ITheme getThemeById(String themeId) { - return themes.get(themeId); - } - - @Override - public ITheme[] getThemes() { - Collection themes = this.themes.values(); - return themes.toArray(new ITheme[themes.size()]); - } - - @Override - public ITheme getDefaultTheme() { - boolean dark = isDarkEclipseTheme(); - return getDefaultTheme(dark); - } - - public ITheme getDefaultTheme(boolean dark) { - for (ITheme theme : this.themes.values()) { - if (theme.isDark() == dark && theme.isDefault()) { - return theme; - } - } - return null; - } - - @Override - public ITheme[] getThemes(boolean dark) { - Collection themes = this.themes.values(); - return themes.stream().filter(theme -> { - return theme.isDark() == dark; - }).collect(Collectors.toList()).toArray(new ITheme[0]); - } - - @Override - public boolean isDarkEclipseTheme() { - return isDarkEclipseTheme(PreferenceUtils.getE4PreferenceCSSThemeId()); - } - - @Override - public boolean isDarkEclipseTheme(String eclipseThemeId) { - return eclipseThemeId != null && eclipseThemeId.toLowerCase().contains("dark"); - } - - @Override - public ITheme getThemeForScope(String scopeName, boolean dark) { - IThemeAssociation association = themeAssociationRegistry.getThemeAssociationFor(scopeName, dark); - if (association != null) { - String themeId = association.getThemeId(); - return getThemeById(themeId); - } - return getDefaultTheme(dark); - } - - @Override - public ITheme getThemeForScope(String scopeName) { - return getThemeForScope(scopeName, isDarkEclipseTheme()); - } - - @Override - public IThemeAssociation[] getThemeAssociationsForScope(String scopeName) { - List associations = new ArrayList<>(); - IThemeAssociation light = themeAssociationRegistry.getThemeAssociationFor(scopeName, false); - if (light == null) { - light = new ThemeAssociation(getDefaultTheme(false).getId(), scopeName, false); - } - associations.add(light); - IThemeAssociation dark = themeAssociationRegistry.getThemeAssociationFor(scopeName, true); - if (dark == null) { - dark = new ThemeAssociation(getDefaultTheme(true).getId(), scopeName, true); - } - associations.add(dark); - return associations.toArray(new IThemeAssociation[associations.size()]); - } - - @Override - public void registerThemeAssociation(IThemeAssociation association) { - themeAssociationRegistry.register(association); - } - - @Override - public void unregisterThemeAssociation(IThemeAssociation association) { - themeAssociationRegistry.unregister(association); - } - - @Override - public IThemeAssociation[] getAllThemeAssociations() { - List associations = themeAssociationRegistry.getThemeAssociations(); - return associations.toArray(new IThemeAssociation[associations.size()]); - } - - @Override - public ITokenProvider getThemeForScope(String scopeName, RGB background) { - return getThemeForScope(scopeName, 0.299 * background.red + 0.587 * background.green + 0.114 * background.blue < 128); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.themes; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.tm4e.ui.internal.utils.PreferenceUtils; +import org.eclipse.tm4e.ui.themes.ITheme; +import org.eclipse.tm4e.ui.themes.IThemeAssociation; +import org.eclipse.tm4e.ui.themes.IThemeManager; +import org.eclipse.tm4e.ui.themes.ITokenProvider; +import org.eclipse.tm4e.ui.themes.ThemeAssociation; + +/** + * TextMate theme manager implementation. + * + */ +public abstract class AbstractThemeManager implements IThemeManager { + + private final Map themes = new LinkedHashMap<>(); + private final ThemeAssociationRegistry themeAssociationRegistry = new ThemeAssociationRegistry(); + + @Override + public void registerTheme(final ITheme theme) { + themes.put(theme.getId(), theme); + } + + @Override + public void unregisterTheme(final ITheme theme) { + themes.remove(theme.getId()); + } + + @Nullable + @Override + public ITheme getThemeById(final String themeId) { + return themes.get(themeId); + } + + @Override + public ITheme[] getThemes() { + final Collection themes = this.themes.values(); + return themes.toArray(ITheme[]::new); + } + + @Override + public ITheme getDefaultTheme() { + final boolean dark = isDarkEclipseTheme(); + return getDefaultTheme(dark); + } + + ITheme getDefaultTheme(final boolean dark) { + for (final ITheme theme : this.themes.values()) { + if (theme.isDark() == dark && theme.isDefault()) { + return theme; + } + } + throw new IllegalStateException("Should never be reached"); + } + + @Override + public ITheme[] getThemes(final boolean dark) { + return themes.values().stream().filter(theme -> theme.isDark() == dark) + .collect(Collectors.toList()).toArray(ITheme[]::new); + } + + @Override + public boolean isDarkEclipseTheme() { + return isDarkEclipseTheme(PreferenceUtils.getE4PreferenceCSSThemeId()); + } + + @Override + public boolean isDarkEclipseTheme(@Nullable final String eclipseThemeId) { + return eclipseThemeId != null && eclipseThemeId.toLowerCase().contains("dark"); + } + + @Override + public ITheme getThemeForScope(final String scopeName, final boolean dark) { + final IThemeAssociation association = themeAssociationRegistry.getThemeAssociationFor(scopeName, dark); + if (association != null) { + final String themeId = association.getThemeId(); + final var theme = getThemeById(themeId); + if (theme != null) { + return theme; + } + } + return getDefaultTheme(dark); + } + + @Override + public ITheme getThemeForScope(final String scopeName) { + return getThemeForScope(scopeName, isDarkEclipseTheme()); + } + + @Override + public IThemeAssociation[] getThemeAssociationsForScope(final String scopeName) { + final List associations = new ArrayList<>(); + IThemeAssociation light = themeAssociationRegistry.getThemeAssociationFor(scopeName, false); + if (light == null) { + light = new ThemeAssociation(getDefaultTheme(false).getId(), scopeName, false); + } + associations.add(light); + IThemeAssociation dark = themeAssociationRegistry.getThemeAssociationFor(scopeName, true); + if (dark == null) { + dark = new ThemeAssociation(getDefaultTheme(true).getId(), scopeName, true); + } + associations.add(dark); + return associations.toArray(IThemeAssociation[]::new); + } + + @Override + public void registerThemeAssociation(final IThemeAssociation association) { + themeAssociationRegistry.register(association); + } + + @Override + public void unregisterThemeAssociation(final IThemeAssociation association) { + themeAssociationRegistry.unregister(association); + } + + @Override + public IThemeAssociation[] getAllThemeAssociations() { + final List associations = themeAssociationRegistry.getThemeAssociations(); + return associations.toArray(IThemeAssociation[]::new); + } + + @Override + public ITokenProvider getThemeForScope(final String scopeName, final RGB background) { + return getThemeForScope(scopeName, 0.299 * background.red + + 0.587 * background.green + + 0.114 * background.blue < 128); + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/BaseThemeAssociationRegistry.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/BaseThemeAssociationRegistry.java index 60f816bcb..7622221bd 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/BaseThemeAssociationRegistry.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/BaseThemeAssociationRegistry.java @@ -1,139 +1,138 @@ -/** - * Copyright (c) 2015-2018 Angelo ZERR. +/** + * Copyright (c) 2015-2018 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.themes; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.eclipse.tm4e.ui.themes.IThemeAssociation; - -/** - * Base Theme association registry. - * - */ -public class BaseThemeAssociationRegistry { - - private IThemeAssociation defaultAssociation; - private final Map> eclipseThemeIds; - private List allAssociations; - - public BaseThemeAssociationRegistry() { - eclipseThemeIds = new HashMap<>(); - this.allAssociations = new ArrayList<>(); - } - - public void register(IThemeAssociation association) { - //String eclipseThemeId = association.getEclipseThemeId(); - // when association is marked as default or scope name is defined, - // update the default association or association for a given E4 Theme. - /*if (association.isDefault()) { - if (eclipseThemeId == null) { - defaultAssociation = association; - } else { - register(association, eclipseThemeId); - } - } else if (eclipseThemeId != null) { - register(association, eclipseThemeId); - }*/ - allAssociations.clear(); - } - - public void unregister(IThemeAssociation association) { - //String eclipseThemeId = association.getEclipseThemeId(); - /*if (association.isDefault()) { - if (eclipseThemeId == null) { - defaultAssociation = null; - } - }*/ -// Collection associations = eclipseThemeIds.get(eclipseThemeId); -// if (associations != null) { -// for (IThemeAssociation a : associations) { -// if (a.equals(association)) { -// associations.remove(a); -// break; -// } -// } -// } - allAssociations.clear(); - } - - public IThemeAssociation getThemeAssociationFor(String eclipseThemeId) { - List associations = eclipseThemeIds.get(eclipseThemeId); - if (associations != null) { - if (associations.size() == 1) { - return associations.get(0); - } - /*for (IThemeAssociation association : associations) { - if (association.isDefault()) { - return association; - } - }*/ - } - return null; - } - - public IThemeAssociation[] getThemeAssociations(boolean isDefault) { - /*if (isDefault) { - return getThemeAssociations().stream().filter(theme -> theme.isDefault()).collect(Collectors.toList()) - .toArray(new IThemeAssociation[0]); - }*/ - return getThemeAssociations().toArray(new IThemeAssociation[allAssociations.size()]); - } - - public IThemeAssociation getDefaultAssociation() { - return defaultAssociation; - } - - public IThemeAssociation[] getThemeAssociationsForTheme(String themeId) { - return getThemeAssociations().stream().filter(themeAssociation -> themeId.equals(themeAssociation.getThemeId())) - .collect(Collectors.toList()).toArray(new IThemeAssociation[0]); - } - - public boolean hasThemeAssociationsForTheme(String themeId, String eclipseThemeId) { -// Collection associations = eclipseThemeIds.get(eclipseThemeId); -// if (associations != null) { -// for (IThemeAssociation themeAssociation : associations) { -// if (themeId.equals(themeAssociation.getThemeId())) { -// return eclipseThemeId.equals(themeAssociation.getEclipseThemeId()); -// } -// } -// return false; -// } else { -// Set>> s = eclipseThemeIds.entrySet(); -// for (Entry> entry : s) { -// for (IThemeAssociation themeAssociation : entry.getValue()) { -// if (themeId.equals(themeAssociation.getThemeId())) { -// return eclipseThemeId.equals(themeAssociation.getEclipseThemeId()); -// } -// } -// } -// } - return true; - } - - public List getThemeAssociations() { - if (allAssociations.isEmpty()) { - if (defaultAssociation != null) { - allAssociations.add(defaultAssociation); - } - Collection> associations = eclipseThemeIds.values(); - for (Collection collection : associations) { - allAssociations.addAll(collection); - } - } - return allAssociations; - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.themes; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.ui.themes.IThemeAssociation; + +/** + * Base Theme association registry. + * + * TODO unused code + */ +final class BaseThemeAssociationRegistry { + + @Nullable + private IThemeAssociation defaultAssociation; + private final Map> eclipseThemeIds = new HashMap<>(); + private final List allAssociations = new ArrayList<>(); + + void register(final IThemeAssociation association) { + //String eclipseThemeId = association.getEclipseThemeId(); + // when association is marked as default or scope name is defined, + // update the default association or association for a given E4 Theme. + /*if (association.isDefault()) { + if (eclipseThemeId == null) { + defaultAssociation = association; + } else { + register(association, eclipseThemeId); + } + } else if (eclipseThemeId != null) { + register(association, eclipseThemeId); + }*/ + allAssociations.clear(); + } + + void unregister(final IThemeAssociation association) { + //String eclipseThemeId = association.getEclipseThemeId(); + /*if (association.isDefault()) { + if (eclipseThemeId == null) { + defaultAssociation = null; + } + }*/ +// Collection associations = eclipseThemeIds.get(eclipseThemeId); +// if (associations != null) { +// for (IThemeAssociation a : associations) { +// if (a.equals(association)) { +// associations.remove(a); +// break; +// } +// } +// } + allAssociations.clear(); + } + + @Nullable + IThemeAssociation getThemeAssociationFor(final String eclipseThemeId) { + final List associations = eclipseThemeIds.get(eclipseThemeId); + if (associations != null) { + if (associations.size() == 1) { + return associations.get(0); + } + /*for (IThemeAssociation association : associations) { + if (association.isDefault()) { + return association; + } + }*/ + } + return null; + } + + IThemeAssociation[] getThemeAssociations(final boolean isDefault) { + /*if (isDefault) { + return getThemeAssociations().stream().filter(theme -> theme.isDefault()).collect(Collectors.toList()) + .toArray(IThemeAssociation[]::new); + }*/ + return getThemeAssociations().toArray(IThemeAssociation[]::new); + } + + @Nullable + IThemeAssociation getDefaultAssociation() { + return defaultAssociation; + } + + IThemeAssociation[] getThemeAssociationsForTheme(final String themeId) { + return getThemeAssociations().stream().filter(themeAssociation -> themeId.equals(themeAssociation.getThemeId())) + .collect(Collectors.toList()).toArray(IThemeAssociation[]::new); + } + + boolean hasThemeAssociationsForTheme(final String themeId, final String eclipseThemeId) { +// Collection associations = eclipseThemeIds.get(eclipseThemeId); +// if (associations != null) { +// for (IThemeAssociation themeAssociation : associations) { +// if (themeId.equals(themeAssociation.getThemeId())) { +// return eclipseThemeId.equals(themeAssociation.getEclipseThemeId()); +// } +// } +// return false; +// } else { +// Set>> s = eclipseThemeIds.entrySet(); +// for (Entry> entry : s) { +// for (IThemeAssociation themeAssociation : entry.getValue()) { +// if (themeId.equals(themeAssociation.getThemeId())) { +// return eclipseThemeId.equals(themeAssociation.getEclipseThemeId()); +// } +// } +// } +// } + return true; + } + + List getThemeAssociations() { + if (allAssociations.isEmpty()) { + if (defaultAssociation != null) { + allAssociations.add(defaultAssociation); + } + final var associations = eclipseThemeIds.values(); + for (final var collection : associations) { + allAssociations.addAll(collection); + } + } + return allAssociations; + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/ThemeAssociationRegistry.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/ThemeAssociationRegistry.java index 55a9ed591..bb6eda273 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/ThemeAssociationRegistry.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/ThemeAssociationRegistry.java @@ -1,167 +1,151 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.themes; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.eclipse.tm4e.ui.themes.IThemeAssociation; - -/** - * Theme association registry. - * - */ -public class ThemeAssociationRegistry { - - private final Map scopes; - - private class EclipseThemeAssociation { - - private IThemeAssociation light; - private IThemeAssociation dark; - - public IThemeAssociation getLight() { - return light; - } - - public void setLight(IThemeAssociation light) { - this.light = light; - } - - public IThemeAssociation getDark() { - return dark; - } - - public void setDark(IThemeAssociation dark) { - this.dark = dark; - } - - } - - public ThemeAssociationRegistry() { - scopes = new HashMap<>(); - } - - public IThemeAssociation getThemeAssociationFor(String scopeName, boolean dark) { - // From theme assiocations - IThemeAssociation userAssociation = null; - EclipseThemeAssociation registry = scopes.get(scopeName); - if (registry != null) { - userAssociation = dark ? registry.getDark() : registry.getLight(); - } - if (userAssociation != null) { - return userAssociation; - } - return null; - } - - public void register(IThemeAssociation association) { - String scopeName = association.getScopeName(); - EclipseThemeAssociation registry = scopes.get(scopeName); - if (registry == null) { - registry = new EclipseThemeAssociation(); - scopes.put(scopeName, registry); - } - boolean dark = association.isWhenDark(); - if (dark) { - registry.setDark(association); - } else { - registry.setLight(association); - } - } - - public void unregister(IThemeAssociation association) { - String scopeName = association.getScopeName(); - EclipseThemeAssociation registry = scopes.get(scopeName); - if (registry != null) { - boolean dark = association.isWhenDark(); - if (dark) { - registry.setDark(null); - } else { - registry.setLight(null); - } - } - } - - // public IThemeAssociation getThemeAssociationFor(String scopeName, String - // eclipseThemeId) { - // IThemeAssociation association = null; - // BaseThemeAssociationRegistry registry = scopes.get(scopeName); - // if (registry != null) { - // association = registry.getThemeAssociationFor(eclipseThemeId); - // if (association == null) { - // association = registry.getDefaultAssociation(); - // } - // } - // if (association == null) { - // association = super.getThemeAssociationFor(eclipseThemeId); - // } - // return association != null ? association : getDefaultAssociation(); - // } - - // public IThemeAssociation[] getThemeAssociationsForScope(String scopeName) { - // BaseThemeAssociationRegistry registry = scopes.get(scopeName); - // if (registry != null) { - // // Get the user associations (from preferences) - // List userAssociations = registry.getThemeAssociations(); - // // Get the default associations (from plugin) - // /*List defaultAssociations = - // getThemeAssociations().stream() - // .filter().collect(Collectors.toList()); - // // Add default association if user associations doesn't define it. - // for (IThemeAssociation defaultAssociation : defaultAssociations) { - // if (!(contains(userAssociations, defaultAssociation))) { - // userAssociations.add(defaultAssociation); - // } - // }*/ - // return userAssociations.toArray(new IThemeAssociation[0]); - // } - // return getThemeAssociations(true); - // } - // - // private boolean contains(List userAssociations, - // IThemeAssociation defaultAssociation) { - //// for (IThemeAssociation userAssociation : userAssociations) { - //// if (defaultAssociation.getEclipseThemeId() == null) { - //// if (userAssociation.getEclipseThemeId() == null) { - //// return true; - //// } - //// } else { - //// if - // (defaultAssociation.getEclipseThemeId().equals(userAssociation.getEclipseThemeId())) - // { - //// return true; - //// } - //// } - //// } - // return false; - // } - // - // @Override - public List getThemeAssociations() { - List associations = new ArrayList<>(); - Collection eclipseAssociations = scopes.values(); - for (EclipseThemeAssociation eclipseAssociation : eclipseAssociations) { - if (eclipseAssociation.getLight() != null) { - associations.add(eclipseAssociation.getLight()); - } - if (eclipseAssociation.getDark() != null) { - associations.add(eclipseAssociation.getDark()); - } - } - return associations; - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.themes; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.ui.themes.IThemeAssociation; + +/** + * Theme association registry. + */ +final class ThemeAssociationRegistry { + + private final Map<@Nullable String, @Nullable EclipseThemeAssociation> scopes = new HashMap<>(); + + private static final class EclipseThemeAssociation { + + @Nullable + IThemeAssociation light; + + @Nullable + IThemeAssociation dark; + } + + @Nullable + IThemeAssociation getThemeAssociationFor(final String scopeName, final boolean dark) { + // From theme associations + IThemeAssociation userAssociation = null; + final EclipseThemeAssociation registry = scopes.get(scopeName); + if (registry != null) { + userAssociation = dark ? registry.dark : registry.light; + } + if (userAssociation != null) { + return userAssociation; + } + return null; + } + + void register(final IThemeAssociation association) { + final String scopeName = association.getScopeName(); + EclipseThemeAssociation registry = scopes.get(scopeName); + if (registry == null) { + registry = new EclipseThemeAssociation(); + scopes.put(scopeName, registry); + } + final boolean dark = association.isWhenDark(); + if (dark) { + registry.dark = association; + } else { + registry.light = association; + } + } + + void unregister(final IThemeAssociation association) { + final String scopeName = association.getScopeName(); + final EclipseThemeAssociation registry = scopes.get(scopeName); + if (registry != null) { + final boolean dark = association.isWhenDark(); + if (dark) { + registry.dark = null; + } else { + registry.light = null; + } + } + } + + // IThemeAssociation getThemeAssociationFor(String scopeName, String + // eclipseThemeId) { + // IThemeAssociation association = null; + // BaseThemeAssociationRegistry registry = scopes.get(scopeName); + // if (registry != null) { + // association = registry.getThemeAssociationFor(eclipseThemeId); + // if (association == null) { + // association = registry.getDefaultAssociation(); + // } + // } + // if (association == null) { + // association = super.getThemeAssociationFor(eclipseThemeId); + // } + // return association != null ? association : getDefaultAssociation(); + // } + + // IThemeAssociation[] getThemeAssociationsForScope(String scopeName) { + // BaseThemeAssociationRegistry registry = scopes.get(scopeName); + // if (registry != null) { + // // Get the user associations (from preferences) + // List userAssociations = registry.getThemeAssociations(); + // // Get the default associations (from plugin) + // /*List defaultAssociations = + // getThemeAssociations().stream() + // .filter().collect(Collectors.toList()); + // // Add default association if user associations doesn't define it. + // for (IThemeAssociation defaultAssociation : defaultAssociations) { + // if (!(contains(userAssociations, defaultAssociation))) { + // userAssociations.add(defaultAssociation); + // } + // }*/ + // return userAssociations.toArray(IThemeAssociation[]::new); + // } + // return getThemeAssociations(true); + // } + // + // private boolean contains(List userAssociations, + // IThemeAssociation defaultAssociation) { + //// for (IThemeAssociation userAssociation : userAssociations) { + //// if (defaultAssociation.getEclipseThemeId() == null) { + //// if (userAssociation.getEclipseThemeId() == null) { + //// return true; + //// } + //// } else { + //// if + // (defaultAssociation.getEclipseThemeId().equals(userAssociation.getEclipseThemeId())) + // { + //// return true; + //// } + //// } + //// } + // return false; + // } + // + // @Override + List getThemeAssociations() { + final var associations = new ArrayList(); + final var eclipseAssociations = scopes.values(); + for (final EclipseThemeAssociation eclipseAssociation : eclipseAssociations) { + if (eclipseAssociation == null) + continue; + if (eclipseAssociation.light != null) { + associations.add(eclipseAssociation.light); + } + if (eclipseAssociation.dark != null) { + associations.add(eclipseAssociation.dark); + } + } + return associations; + } + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/ThemeManager.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/ThemeManager.java index e2e78db22..810ee6385 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/ThemeManager.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/ThemeManager.java @@ -1,181 +1,182 @@ -/** - * Copyright (c) 2015, 2021 Angelo ZERR and others. +/** + * Copyright (c) 2015, 2021 Angelo ZERR and others. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.themes; - - -import java.util.Arrays; -import java.util.stream.Collectors; - -import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.preferences.IEclipsePreferences; -import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; -import org.eclipse.core.runtime.preferences.InstanceScope; -import org.eclipse.tm4e.ui.TMUIPlugin; -import org.eclipse.tm4e.ui.internal.preferences.PreferenceConstants; -import org.eclipse.tm4e.ui.internal.preferences.PreferenceHelper; -import org.eclipse.tm4e.ui.themes.IThemeAssociation; -import org.eclipse.tm4e.ui.themes.Theme; -import org.eclipse.tm4e.ui.themes.ThemeAssociation; -import org.eclipse.tm4e.ui.utils.PreferenceUtils; -import org.osgi.service.prefs.BackingStoreException; - -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; - -/** - * Theme manager singleton. - */ -public class ThemeManager extends AbstractThemeManager { - - // "themes" extension point - private static final String EXTENSION_THEMES = "themes"; //$NON-NLS-1$ - - // "theme" declaration - private static final String THEME_ELT = "theme"; //$NON-NLS-1$ - - // "themeAssociation" declaration - private static final String THEME_ASSOCIATION_ELT = "themeAssociation"; //$NON-NLS-1$ - - private static ThemeManager INSTANCE; - - public static ThemeManager getInstance() { - if (INSTANCE != null) { - return INSTANCE; - } - INSTANCE = createInstance(); - return INSTANCE; - } - - private static synchronized ThemeManager createInstance() { - if (INSTANCE != null) { - return INSTANCE; - } - ThemeManager manager = new ThemeManager(); - manager.load(); - return manager; - } - - private ThemeManager() { - } - - private void load() { - loadThemesFromExtensionPoints(); - loadThemesFromPreferences(); - } - - /** - * Load TextMate Themes from extension point. - */ - private void loadThemesFromExtensionPoints() { - IConfigurationElement[] cf = Platform.getExtensionRegistry().getConfigurationElementsFor(TMUIPlugin.PLUGIN_ID, - EXTENSION_THEMES); - for (IConfigurationElement ce : cf) { - String name = ce.getName(); - if (THEME_ELT.equals(name)) { - super.registerTheme(new Theme(ce)); - } else if (THEME_ASSOCIATION_ELT.equals(name)) { - super.registerThemeAssociation(new ThemeAssociation(ce)); - } - } - } - - /** - * Load TextMate Themes from preferences. - */ - private void loadThemesFromPreferences() { - // Load Theme definitions from the - // "${workspace_loc}/metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.tm4e.ui.prefs" - IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(TMUIPlugin.PLUGIN_ID); - String json = prefs.get(PreferenceConstants.THEMES, null); - if (json != null) { - for (JsonObject element : new Gson().fromJson(json, JsonObject[].class)) { - String name = element.get("id").getAsString(); - super.registerTheme(new Theme(name, element.get("path").getAsString(), name, element.get("dark").getAsBoolean(), false)); - } - } - - json = prefs.get(PreferenceConstants.THEME_ASSOCIATIONS, null); - if (json != null) { - IThemeAssociation[] themeAssociations = PreferenceHelper.loadThemeAssociations(json); - for (IThemeAssociation association : themeAssociations) { - super.registerThemeAssociation(association); - } - } - } - - @Override - public void save() throws BackingStoreException { - IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(TMUIPlugin.PLUGIN_ID); - // Save Themes in the - // "${workspace_loc}/metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.tm4e.ui.prefs" - prefs.put(PreferenceConstants.THEMES, Arrays.stream(getThemes()) // - .filter(t -> t.getPluginId() == null) // - .map(theme -> { - JsonObject json = new JsonObject(); - json.addProperty("id", theme.getId()); - json.addProperty("path", theme.getPath()); - json.addProperty("dark", theme.isDark()); - return json; - }).collect(JsonArray::new, (JsonArray array, JsonObject object) -> array.add(object), (r,r1) -> {}) - .toString()); - - // Save Theme associations in the - // "${workspace_loc}/metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.tm4e.ui.prefs" - String json = PreferenceHelper.toJsonThemeAssociations(Arrays.stream(getAllThemeAssociations()) - .filter(t -> t.getPluginId() == null).collect(Collectors.toList())); - prefs.put(PreferenceConstants.THEME_ASSOCIATIONS, json); - - // Save preferences - prefs.flush(); - } - - /** - * Add preference change listener to observe changed of Eclipse E4 Theme and - * TextMate theme association with grammar. - * - * @param themeChangeListener - */ - public void addPreferenceChangeListener(IPreferenceChangeListener themeChangeListener) { - // Observe change of Eclipse E4 Theme - IEclipsePreferences preferences = PreferenceUtils.getE4PreferenceStore(); - if (preferences != null) { - preferences.addPreferenceChangeListener(themeChangeListener); - } - // Observe change of TextMate Theme association - preferences = InstanceScope.INSTANCE.getNode(TMUIPlugin.PLUGIN_ID); - if (preferences != null) { - preferences.addPreferenceChangeListener(themeChangeListener); - } - } - - /** - * Remove preference change listener to observe changed of Eclipse E4 Theme and - * TextMate theme association with grammar. - * - * @param themeChangeListener - */ - public void removePreferenceChangeListener(IPreferenceChangeListener themeChangeListener) { - // Observe change of Eclipse E4 Theme - IEclipsePreferences preferences = PreferenceUtils.getE4PreferenceStore(); - if (preferences != null) { - preferences.removePreferenceChangeListener(themeChangeListener); - } - // Observe change of TextMate Theme association - preferences = InstanceScope.INSTANCE.getNode(TMUIPlugin.PLUGIN_ID); - if (preferences != null) { - preferences.removePreferenceChangeListener(themeChangeListener); - } - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.themes; + +import java.util.Arrays; +import java.util.stream.Collectors; + +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.ui.TMUIPlugin; +import org.eclipse.tm4e.ui.internal.preferences.PreferenceConstants; +import org.eclipse.tm4e.ui.internal.preferences.PreferenceHelper; +import org.eclipse.tm4e.ui.internal.utils.PreferenceUtils; +import org.eclipse.tm4e.ui.themes.IThemeAssociation; +import org.eclipse.tm4e.ui.themes.Theme; +import org.eclipse.tm4e.ui.themes.ThemeAssociation; +import org.osgi.service.prefs.BackingStoreException; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + +/** + * Theme manager singleton. + */ +public final class ThemeManager extends AbstractThemeManager { + + // "themes" extension point + private static final String EXTENSION_THEMES = "themes"; //$NON-NLS-1$ + + // "theme" declaration + private static final String THEME_ELT = "theme"; //$NON-NLS-1$ + + // "themeAssociation" declaration + private static final String THEME_ASSOCIATION_ELT = "themeAssociation"; //$NON-NLS-1$ + + @Nullable + private static ThemeManager INSTANCE; + + public static ThemeManager getInstance() { + if (INSTANCE != null) { + return INSTANCE; + } + INSTANCE = createInstance(); + return INSTANCE; + } + + private static synchronized ThemeManager createInstance() { + if (INSTANCE != null) { + return INSTANCE; + } + final ThemeManager manager = new ThemeManager(); + manager.load(); + return manager; + } + + private ThemeManager() { + } + + private void load() { + loadThemesFromExtensionPoints(); + loadThemesFromPreferences(); + } + + /** + * Load TextMate Themes from extension point. + */ + private void loadThemesFromExtensionPoints() { + final var config = Platform.getExtensionRegistry().getConfigurationElementsFor(TMUIPlugin.PLUGIN_ID, + EXTENSION_THEMES); + for (final var configElement : config) { + final String name = configElement.getName(); + switch (name) { + case THEME_ELT: + super.registerTheme(new Theme(configElement)); + break; + case THEME_ASSOCIATION_ELT: + super.registerThemeAssociation(new ThemeAssociation(configElement)); + break; + } + } + } + + /** + * Load TextMate Themes from preferences. + */ + private void loadThemesFromPreferences() { + // Load Theme definitions from the + // "${workspace_loc}/metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.tm4e.ui.prefs" + final var prefs = InstanceScope.INSTANCE.getNode(TMUIPlugin.PLUGIN_ID); + String json = prefs.get(PreferenceConstants.THEMES, null); + if (json != null) { + for (final var element : new Gson().fromJson(json, JsonObject[].class)) { + final String name = element.get("id").getAsString(); + super.registerTheme(new Theme(name, element.get("path").getAsString(), name, element.get("dark").getAsBoolean(), false)); + } + } + + json = prefs.get(PreferenceConstants.THEME_ASSOCIATIONS, null); + if (json != null) { + final var themeAssociations = PreferenceHelper.loadThemeAssociations(json); + for (final IThemeAssociation association : themeAssociations) { + super.registerThemeAssociation(association); + } + } + } + + @Override + public void save() throws BackingStoreException { + final var prefs = InstanceScope.INSTANCE.getNode(TMUIPlugin.PLUGIN_ID); + // Save Themes in the + // "${workspace_loc}/metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.tm4e.ui.prefs" + prefs.put(PreferenceConstants.THEMES, Arrays.stream(getThemes()) // + .filter(t -> t.getPluginId() == null) // + .map(theme -> { + final JsonObject json = new JsonObject(); + json.addProperty("id", theme.getId()); + json.addProperty("path", theme.getPath()); + json.addProperty("dark", theme.isDark()); + return json; + }).collect(JsonArray::new, (final JsonArray array, final JsonObject object) -> array.add(object), (r,r1) -> {}) + .toString()); + + // Save Theme associations in the + // "${workspace_loc}/metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.tm4e.ui.prefs" + final String json = PreferenceHelper.toJsonThemeAssociations(Arrays.stream(getAllThemeAssociations()) + .filter(t -> t.getPluginId() == null).collect(Collectors.toList())); + prefs.put(PreferenceConstants.THEME_ASSOCIATIONS, json); + + // Save preferences + prefs.flush(); + } + + /** + * Add preference change listener to observe changed of Eclipse E4 Theme and + * TextMate theme association with grammar. + * + * @param themeChangeListener + */ + public void addPreferenceChangeListener(final IPreferenceChangeListener themeChangeListener) { + // Observe change of Eclipse E4 Theme + var preferences = PreferenceUtils.getE4PreferenceStore(); + if (preferences != null) { + preferences.addPreferenceChangeListener(themeChangeListener); + } + // Observe change of TextMate Theme association + preferences = InstanceScope.INSTANCE.getNode(TMUIPlugin.PLUGIN_ID); + if (preferences != null) { + preferences.addPreferenceChangeListener(themeChangeListener); + } + } + + /** + * Remove preference change listener to observe changed of Eclipse E4 Theme and + * TextMate theme association with grammar. + * + * @param themeChangeListener + */ + public void removePreferenceChangeListener(final IPreferenceChangeListener themeChangeListener) { + // Observe change of Eclipse E4 Theme + var preferences = PreferenceUtils.getE4PreferenceStore(); + if (preferences != null) { + preferences.removePreferenceChangeListener(themeChangeListener); + } + // Observe change of TextMate Theme association + preferences = InstanceScope.INSTANCE.getNode(TMUIPlugin.PLUGIN_ID); + if (preferences != null) { + preferences.removePreferenceChangeListener(themeChangeListener); + } + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/WorkingCopyThemeManager.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/WorkingCopyThemeManager.java index 289fe92eb..7a07e39d1 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/WorkingCopyThemeManager.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/WorkingCopyThemeManager.java @@ -1,125 +1,137 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.themes; - -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.tm4e.ui.themes.ITheme; -import org.eclipse.tm4e.ui.themes.IThemeAssociation; -import org.eclipse.tm4e.ui.themes.IThemeManager; -import org.osgi.service.prefs.BackingStoreException; - -/** - * Working copy of theme manager. - * - */ -public class WorkingCopyThemeManager extends AbstractThemeManager { - - private final IThemeManager manager; - - private List themeAdded; - private List themeRemoved; - - private List associationAdded; - private List associationRemoved; - - public WorkingCopyThemeManager(IThemeManager manager) { - this.manager = manager; - load(); - } - - private void load() { - // Copy themes - ITheme[] themes = manager.getThemes(); - for (ITheme theme : themes) { - super.registerTheme(theme); - } - // Copy theme associations - IThemeAssociation[] associations = manager.getAllThemeAssociations(); - for (IThemeAssociation association : associations) { - super.registerThemeAssociation(association); - } - } - - @Override - public void registerTheme(ITheme theme) { - super.registerTheme(theme); - if (themeAdded == null) { - themeAdded = new ArrayList<>(); - } - themeAdded.add(theme); - } - - @Override - public void unregisterTheme(ITheme theme) { - super.unregisterTheme(theme); - if (themeAdded != null && themeAdded.contains(theme)) { - themeAdded.remove(theme); - } else { - if (themeRemoved == null) { - themeRemoved = new ArrayList<>(); - } - themeRemoved.add(theme); - } - } - - @Override - public void registerThemeAssociation(IThemeAssociation association) { - super.registerThemeAssociation(association); - if (associationAdded == null) { - associationAdded = new ArrayList<>(); - } - associationAdded.add(association); - } - - @Override - public void unregisterThemeAssociation(IThemeAssociation association) { - super.unregisterThemeAssociation(association); - if (associationAdded != null && associationAdded.contains(association)) { - associationAdded.remove(association); - } else { - if (associationRemoved == null) { - associationRemoved = new ArrayList<>(); - } - associationRemoved.add(association); - } - } - - @Override - public void save() throws BackingStoreException { - if (themeAdded != null) { - for (ITheme theme : themeAdded) { - manager.registerTheme(theme); - } - } - if (themeRemoved != null) { - for (ITheme theme : themeRemoved) { - manager.unregisterTheme(theme); - } - } - if (associationAdded != null) { - for (IThemeAssociation association : associationAdded) { - manager.registerThemeAssociation(association); - } - } - if (associationRemoved != null) { - for (IThemeAssociation association : associationRemoved) { - manager.unregisterThemeAssociation(association); - } - } - if (themeAdded != null || themeRemoved != null || associationAdded != null || associationRemoved != null) { - manager.save(); - } - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.themes; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.ui.themes.ITheme; +import org.eclipse.tm4e.ui.themes.IThemeAssociation; +import org.eclipse.tm4e.ui.themes.IThemeManager; +import org.osgi.service.prefs.BackingStoreException; + +/** + * Working copy of theme manager. + * + */ +public final class WorkingCopyThemeManager extends AbstractThemeManager { + + private final IThemeManager manager; + + @Nullable + private List themeAdded; + + @Nullable + private List themeRemoved; + + @Nullable + private List associationAdded; + + @Nullable + private List associationRemoved; + + public WorkingCopyThemeManager(final IThemeManager manager) { + this.manager = manager; + load(); + } + + private void load() { + // Copy themes + final ITheme[] themes = manager.getThemes(); + for (final ITheme theme : themes) { + super.registerTheme(theme); + } + // Copy theme associations + final IThemeAssociation[] associations = manager.getAllThemeAssociations(); + for (final IThemeAssociation association : associations) { + super.registerThemeAssociation(association); + } + } + + @Override + public void registerTheme(final ITheme theme) { + super.registerTheme(theme); + var themeAdded = this.themeAdded; + if (themeAdded == null) { + themeAdded = this.themeAdded = new ArrayList<>(); + } + themeAdded.add(theme); + } + + @Override + public void unregisterTheme(final ITheme theme) { + super.unregisterTheme(theme); + var themeAdded = this.themeAdded; + if (themeAdded != null && themeAdded.contains(theme)) { + themeAdded.remove(theme); + } else { + var themeRemoved = this.themeRemoved; + if (themeRemoved == null) { + themeRemoved = this.themeRemoved = new ArrayList<>(); + } + themeRemoved.add(theme); + } + } + + @Override + public void registerThemeAssociation(final IThemeAssociation association) { + super.registerThemeAssociation(association); + var associationAdded = this.associationAdded; + if (associationAdded == null) { + associationAdded = this.associationAdded = new ArrayList<>(); + } + associationAdded.add(association); + } + + @Override + public void unregisterThemeAssociation(final IThemeAssociation association) { + super.unregisterThemeAssociation(association); + var associationAdded = this.associationAdded; + if (associationAdded != null && associationAdded.contains(association)) { + associationAdded.remove(association); + } else { + var associationRemoved = this.associationRemoved; + if (associationRemoved == null) { + associationRemoved = this.associationRemoved = new ArrayList<>(); + } + associationRemoved.add(association); + } + } + + @Override + public void save() throws BackingStoreException { + if (themeAdded != null) { + for (final var theme : themeAdded) { + manager.registerTheme(theme); + } + } + if (themeRemoved != null) { + for (final var theme : themeRemoved) { + manager.unregisterTheme(theme); + } + } + if (associationAdded != null) { + for (final var association : associationAdded) { + manager.registerThemeAssociation(association); + } + } + if (associationRemoved != null) { + for (final var association : associationRemoved) { + manager.unregisterThemeAssociation(association); + } + } + if (themeAdded != null || themeRemoved != null || associationAdded != null || associationRemoved != null) { + manager.save(); + } + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/package-info.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/package-info.java new file mode 100644 index 000000000..fd0db7b9e --- /dev/null +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/themes/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.ui.internal.themes; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/utils/ClassHelper.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/utils/ClassHelper.java similarity index 53% rename from org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/utils/ClassHelper.java rename to org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/utils/ClassHelper.java index ab86f0fb4..ef5f6b5ad 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/utils/ClassHelper.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/utils/ClassHelper.java @@ -1,52 +1,58 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.utils; - -import java.lang.reflect.Field; - -/** - * Class Reflection utilities. - * - */ -public class ClassHelper { - - public static T getFieldValue(Object object, String name, Class clazz) { - Field f = getDeclaredField(clazz, name); - if (f != null) { - try { - return (T) f.get(object); - } catch (Exception e) { - return null; - } - } - return null; - } - - public static T getFieldValue(Object object, String name) { - return getFieldValue(object, name, object.getClass()); - } - - public static Field getDeclaredField(Class clazz, String name) { - if (clazz == null) { - return null; - } - try { - Field f = clazz.getDeclaredField(name); - f.setAccessible(true); - return f; - } catch (NoSuchFieldException e) { - return getDeclaredField(clazz.getSuperclass(), name); - } catch (SecurityException e) { - return null; - } - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.utils; + +import java.lang.reflect.Field; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * Class Reflection utilities. + * + */ +public final class ClassHelper { + + @Nullable + @SuppressWarnings("unchecked") + public static T getFieldValue(final Object object, final String name, final Class clazz) { + final Field f = getDeclaredField(clazz, name); + if (f != null) { + try { + return (T) f.get(object); + } catch (final Exception e) { + return null; + } + } + return null; + } + + @Nullable + public static T getFieldValue(final Object object, final String name) { + return getFieldValue(object, name, object.getClass()); + } + + @Nullable + public static Field getDeclaredField(@Nullable final Class clazz, final String name) { + if (clazz == null) { + return null; + } + try { + final Field f = clazz.getDeclaredField(name); + f.setAccessible(true); + return f; + } catch (final NoSuchFieldException e) { + return getDeclaredField(clazz.getSuperclass(), name); + } catch (final SecurityException e) { + return null; + } + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/utils/ContentTypeHelper.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/utils/ContentTypeHelper.java similarity index 66% rename from org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/utils/ContentTypeHelper.java rename to org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/utils/ContentTypeHelper.java index eff03af33..9306b907b 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/utils/ContentTypeHelper.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/utils/ContentTypeHelper.java @@ -1,231 +1,231 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.utils; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedHashSet; - -import org.eclipse.core.filebuffers.FileBuffers; -import org.eclipse.core.filebuffers.ITextFileBuffer; -import org.eclipse.core.filebuffers.ITextFileBufferManager; -import org.eclipse.core.filesystem.EFS; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IStorage; -import org.eclipse.core.resources.IWorkspaceRoot; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.ListenerList; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.core.runtime.content.IContentTypeManager; -import org.eclipse.jface.text.IDocument; -import org.eclipse.tm4e.ui.internal.model.DocumentInputStream; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IStorageEditorInput; - -/** - * {@link IContentType} utilities. - * - */ -public class ContentTypeHelper { - - /** - * Find the content types from the given {@link IDocument} and null otherwise. - * - * @param document - * @return the content types from the given {@link IDocument} and null - * otherwise. - * @throws CoreException - */ - public static ContentTypeInfo findContentTypes(IDocument document) throws CoreException { - // Find content types from FileBuffers - ContentTypeInfo contentTypes = findContentTypesFromFileBuffers(document); - if (contentTypes != null) { - return contentTypes; - } - // Find content types from the IEditorInput - return findContentTypesFromEditorInput(document); - } - - /** - * Find the content type with the given contentTypeId - * - * @param contentTypeId - * @return matching content type or null - */ - public static IContentType getContentTypeById(String contentTypeId) { - IContentTypeManager manager = Platform.getContentTypeManager(); - return manager.getContentType(contentTypeId); - } - - // ------------------------- Find content types from FileBuffers - - /** - * Find the content types from the given {@link IDocument} by using - * {@link ITextFileBufferManager} and null otherwise. - * - * @param document - * @return the content types from the given {@link IDocument} by using - * {@link ITextFileBufferManager} and null otherwise. - * @throws CoreException - */ - private static ContentTypeInfo findContentTypesFromFileBuffers(IDocument document) throws CoreException { - ITextFileBufferManager bufferManager = FileBuffers.getTextFileBufferManager(); - ITextFileBuffer buffer = bufferManager.getTextFileBuffer(document); - if (buffer != null) { - return getContentTypes(buffer); - } - return null; - } - - /** - * Returns the content types from the given {@link ITextFileBuffer}. - * - * @param buffer - * @return the content types from the given {@link ITextFileBuffer}. - * @throws CoreException - */ - private static ContentTypeInfo getContentTypes(ITextFileBuffer buffer) throws CoreException { - try { - String fileName = buffer.getFileStore().getName(); - Collection contentTypes = new LinkedHashSet<>(); - IContentType bufferContentType = buffer.getContentType(); - if (bufferContentType != null) { - contentTypes.add(bufferContentType); - } - if (buffer.isDirty()) { - // Buffer is dirty (content of the filesystem is not synch with - // the editor content), use IDocument content. - try (InputStream input = new DocumentInputStream(buffer.getDocument())){ - IContentType[] contentTypesForInput = Platform.getContentTypeManager().findContentTypesFor(input, fileName); - if (contentTypesForInput != null) { - contentTypes.addAll(Arrays.asList(contentTypesForInput)); - return new ContentTypeInfo(fileName, contentTypes.toArray(IContentType[]::new)); - } - } - } - - // Buffer is synchronized with filesystem content - try (InputStream contents = getContents(buffer)){ - contentTypes.addAll(Arrays.asList(Platform.getContentTypeManager().findContentTypesFor(contents, fileName))); - return new ContentTypeInfo(fileName, contentTypes.toArray(IContentType[]::new)); - } catch (Throwable e) { - return null; - } - } catch (IOException x) { - x.printStackTrace(); - return null; - } - } - - /** - * Returns the content of the given buffer. - * - * @param buffer - * @return the content of the given buffer. - * @throws CoreException - */ - private static InputStream getContents(ITextFileBuffer buffer) throws CoreException { - IPath path = buffer.getLocation(); - if (path != null) { - IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); - IFile file = workspaceRoot.getFile(path); - if (file.exists() && buffer.isSynchronized()) { - return file.getContents(); - } - } - return buffer.getFileStore().openInputStream(EFS.NONE, null); - } - - // ------------------------- Find content types from FileBuffers - - /** - * Find the content types from the given {@link IDocument} by using - * {@link IEditorInput} and null otherwise. - * - * @param document - * @return the content types from the given {@link IDocument} by using - * {@link IEditorInput} and null otherwise. - */ - private static ContentTypeInfo findContentTypesFromEditorInput(IDocument document) { - IEditorInput editorInput = getEditorInput(document); - if (editorInput != null) { - if (editorInput instanceof IStorageEditorInput) { - InputStream input = null; - try { - IStorage storage = ((IStorageEditorInput) editorInput).getStorage(); - String fileName = storage.getName(); - input = storage.getContents(); - return new ContentTypeInfo(fileName, - Platform.getContentTypeManager().findContentTypesFor(input, fileName)); - } catch (Exception e) { - return null; - } finally { - try { - if (input != null) - input.close(); - } catch (IOException x) { - } - } - } else { - // TODO: manage other type of IEditorInput - } - } - return null; - } - - /** - * Returns the {@link IEditorInput} from the given document and null otherwise. - * - * @param document - * @return the {@link IEditorInput} from the given document and null otherwise. - */ - private static IEditorInput getEditorInput(IDocument document) { - try { - // This utilities class is very ugly, I have not found a clean mean - // to retrieve the IEditorInput linked to a document. - // Here the strategy to retrieve the IEditorInput: - - // AbstractDocumentProvider#ElementInfo add a IDocumentListener to - // the document. - // ElementInfo contains a fElement which is the IEditorInput (like - // ISorageEditorInput, see StorageDocumentProvider) - - // get list of IDocumentListener - ListenerList listeners = ClassHelper.getFieldValue(document, "fDocumentListeners"); - if (listeners != null) { - // Get AbstractDocumentProvider#ElementInfo - Object[] l = listeners.getListeners(); - for (int i = 0; i < l.length; i++) { - Object /* AbstractDocumentProvider#ElementInfo */ info = l[i]; - try { - /* The element for which the info is stored */ - Object input = ClassHelper.getFieldValue(info, "fElement"); - if (input instanceof IEditorInput) { - return (IEditorInput) input; - } - } catch (Exception e) { - - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - -} +/** + * Copyright (c) 2015-2017 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedHashSet; + +import org.eclipse.core.filebuffers.FileBuffers; +import org.eclipse.core.filebuffers.ITextFileBuffer; +import org.eclipse.core.filebuffers.ITextFileBufferManager; +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IStorage; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.ListenerList; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.content.IContentTypeManager; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.text.IDocument; +import org.eclipse.tm4e.ui.internal.model.DocumentInputStream; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IStorageEditorInput; + +/** + * {@link IContentType} utilities. + * + */ +public final class ContentTypeHelper { + + /** + * Find the content types from the given {@link IDocument} and null otherwise. + * + * @param document + * @return the content types from the given {@link IDocument} and null otherwise. + * @throws CoreException + */ + @Nullable + public static ContentTypeInfo findContentTypes(final IDocument document) throws CoreException { + // Find content types from FileBuffers + final ContentTypeInfo contentTypes = findContentTypesFromFileBuffers(document); + if (contentTypes != null) { + return contentTypes; + } + // Find content types from the IEditorInput + return findContentTypesFromEditorInput(document); + } + + /** + * Find the content type with the given contentTypeId + * + * @param contentTypeId + * @return matching content type or null + */ + @Nullable + public static IContentType getContentTypeById(final String contentTypeId) { + final IContentTypeManager manager = Platform.getContentTypeManager(); + return manager.getContentType(contentTypeId); + } + + // ------------------------- Find content types from FileBuffers + + /** + * Find the content types from the given {@link IDocument} by using + * {@link ITextFileBufferManager} and null otherwise. + * + * @param document + * @return the content types from the given {@link IDocument} by using + * {@link ITextFileBufferManager} and null otherwise. + * @throws CoreException + */ + @Nullable + private static ContentTypeInfo findContentTypesFromFileBuffers(final IDocument document) throws CoreException { + final ITextFileBufferManager bufferManager = FileBuffers.getTextFileBufferManager(); + final ITextFileBuffer buffer = bufferManager.getTextFileBuffer(document); + if (buffer != null) { + return getContentTypes(buffer); + } + return null; + } + + /** + * Returns the content types from the given {@link ITextFileBuffer}. + * + * @param buffer + * @return the content types from the given {@link ITextFileBuffer}. + * @throws CoreException + */ + @Nullable + private static ContentTypeInfo getContentTypes(final ITextFileBuffer buffer) throws CoreException { + try { + final String fileName = buffer.getFileStore().getName(); + final Collection contentTypes = new LinkedHashSet<>(); + final IContentType bufferContentType = buffer.getContentType(); + if (bufferContentType != null) { + contentTypes.add(bufferContentType); + } + if (buffer.isDirty()) { + // Buffer is dirty (content of the filesystem is not synch with + // the editor content), use IDocument content. + try (InputStream input = new DocumentInputStream(buffer.getDocument())) { + final IContentType[] contentTypesForInput = Platform.getContentTypeManager().findContentTypesFor(input, fileName); + if (contentTypesForInput != null) { + contentTypes.addAll(Arrays.asList(contentTypesForInput)); + return new ContentTypeInfo(fileName, contentTypes.toArray(IContentType[]::new)); + } + } + } + + // Buffer is synchronized with filesystem content + try (InputStream contents = getContents(buffer)) { + contentTypes.addAll(Arrays.asList(Platform.getContentTypeManager().findContentTypesFor(contents, fileName))); + return new ContentTypeInfo(fileName, contentTypes.toArray(IContentType[]::new)); + } catch (final Throwable e) { + return null; + } + } catch (final IOException x) { + x.printStackTrace(); + return null; + } + } + + /** + * Returns the content of the given buffer. + * + * @param buffer + * @return the content of the given buffer. + * @throws CoreException + */ + private static InputStream getContents(final ITextFileBuffer buffer) throws CoreException { + final IPath path = buffer.getLocation(); + if (path != null) { + final IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); + final IFile file = workspaceRoot.getFile(path); + if (file.exists() && buffer.isSynchronized()) { + return file.getContents(); + } + } + return buffer.getFileStore().openInputStream(EFS.NONE, null); + } + + // ------------------------- Find content types from FileBuffers + + /** + * Find the content types from the given {@link IDocument} by using + * {@link IEditorInput} and null otherwise. + * + * @param document + * @return the content types from the given {@link IDocument} by using + * {@link IEditorInput} and null otherwise. + */ + @Nullable + private static ContentTypeInfo findContentTypesFromEditorInput(final IDocument document) { + final IEditorInput editorInput = getEditorInput(document); + if (editorInput != null) { + if (editorInput instanceof IStorageEditorInput) { + try { + final IStorage storage = ((IStorageEditorInput) editorInput).getStorage(); + final String fileName = storage.getName(); + try (InputStream input = storage.getContents()) { + return new ContentTypeInfo(fileName, + Platform.getContentTypeManager().findContentTypesFor(input, fileName)); + } + } catch (final Exception e) { + return null; + } + } /*else { + // TODO: manage other type of IEditorInput + }*/ + } + return null; + } + + /** + * Returns the {@link IEditorInput} from the given document and null otherwise. + * + * @param document + * @return the {@link IEditorInput} from the given document and null otherwise. + */ + @Nullable + private static IEditorInput getEditorInput(final IDocument document) { + try { + // This utilities class is very ugly, I have not found a clean mean + // to retrieve the IEditorInput linked to a document. + // Here the strategy to retrieve the IEditorInput: + + // AbstractDocumentProvider#ElementInfo add a IDocumentListener to + // the document. + // ElementInfo contains a fElement which is the IEditorInput (like + // ISorageEditorInput, see StorageDocumentProvider) + + // get list of IDocumentListener + final ListenerList listeners = ClassHelper.getFieldValue(document, "fDocumentListeners"); + if (listeners != null) { + // Get AbstractDocumentProvider#ElementInfo + final Object[] l = listeners.getListeners(); + for (int i = 0; i < l.length; i++) { + final Object /* AbstractDocumentProvider#ElementInfo */ info = l[i]; + try { + /* The element for which the info is stored */ + final Object input = ClassHelper.getFieldValue(info, "fElement"); + if (input instanceof IEditorInput) { + return (IEditorInput) input; + } + } catch (final Exception e) { + + } + } + } + } catch (final Exception e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/utils/ContentTypeInfo.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/utils/ContentTypeInfo.java similarity index 80% rename from org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/utils/ContentTypeInfo.java rename to org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/utils/ContentTypeInfo.java index 0923bccad..7dcc939b6 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/utils/ContentTypeInfo.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/utils/ContentTypeInfo.java @@ -9,30 +9,28 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.ui.utils; - -import org.eclipse.core.runtime.content.IContentType; - -/** - * - * @author azerr - * - */ -public class ContentTypeInfo { - - private final String fileName; - private final IContentType[] contentTypes; - - public ContentTypeInfo(String fileName, IContentType[] contentTypes) { - this.fileName = fileName; - this.contentTypes = contentTypes; - } - - public String getFileName() { - return fileName; - } - - public IContentType[] getContentTypes() { - return contentTypes; - } -} +package org.eclipse.tm4e.ui.internal.utils; + +import org.eclipse.core.runtime.content.IContentType; + +/** + * @author azerr + */ +public final class ContentTypeInfo { + + private final String fileName; + private final IContentType[] contentTypes; + + public ContentTypeInfo(final String fileName, final IContentType[] contentTypes) { + this.fileName = fileName; + this.contentTypes = contentTypes; + } + + public String getFileName() { + return fileName; + } + + public IContentType[] getContentTypes() { + return contentTypes; + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/utils/PreferenceUtils.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/utils/PreferenceUtils.java similarity index 82% rename from org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/utils/PreferenceUtils.java rename to org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/utils/PreferenceUtils.java index 072449a77..f84e0fa59 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/utils/PreferenceUtils.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/utils/PreferenceUtils.java @@ -9,57 +9,62 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.ui.utils; - -import org.eclipse.core.runtime.preferences.IEclipsePreferences; -import org.eclipse.core.runtime.preferences.InstanceScope; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.tm4e.ui.TMUIPlugin; -import org.eclipse.tm4e.ui.internal.preferences.PreferenceConstants; - -public class PreferenceUtils { - - private static final String E4_CSS_PREFERENCE_NAME = "org.eclipse.e4.ui.css.swt.theme"; //$NON-NLS-1$ - private static final String EDITORS_PREFERENCE_NAME = "org.eclipse.ui.editors"; //$NON-NLS-1$ - - private PreferenceUtils() { - } - - /** - * Get e4 preferences store - * - * @return preferences store - */ - public static IEclipsePreferences getE4PreferenceStore() { - return InstanceScope.INSTANCE.getNode(E4_CSS_PREFERENCE_NAME); - } - - /** - * Get Id of the current eclipse theme - * - * @return themeIf of the current eclipse theme - */ - public static String getE4PreferenceCSSThemeId() { - IEclipsePreferences preferences = getE4PreferenceStore(); - return preferences != null ? preferences.get(PreferenceConstants.E4_THEME_ID, null) : null; - } - - /** - * Get editors preferences store - * - * @return preferences store - */ - public static IEclipsePreferences getEditorsPreferenceStore() { - return InstanceScope.INSTANCE.getNode(EDITORS_PREFERENCE_NAME); - } - - /** - * Get TM4E preferences store - * - * @return preferences store - */ - public static IPreferenceStore getTM4EPreferencesStore() { - return TMUIPlugin.getDefault().getPreferenceStore(); - - } -} +package org.eclipse.tm4e.ui.internal.utils; + +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.tm4e.ui.TMUIPlugin; +import org.eclipse.tm4e.ui.internal.preferences.PreferenceConstants; + +public final class PreferenceUtils { + + private static final String E4_CSS_PREFERENCE_NAME = "org.eclipse.e4.ui.css.swt.theme"; //$NON-NLS-1$ + private static final String EDITORS_PREFERENCE_NAME = "org.eclipse.ui.editors"; //$NON-NLS-1$ + + private PreferenceUtils() { + } + + /** + * Get e4 preferences store + * + * @return preferences store + */ + @Nullable + public static IEclipsePreferences getE4PreferenceStore() { + return InstanceScope.INSTANCE.getNode(E4_CSS_PREFERENCE_NAME); + } + + /** + * Get Id of the current eclipse theme + * + * @return themeIf of the current eclipse theme + */ + @Nullable + public static String getE4PreferenceCSSThemeId() { + final IEclipsePreferences preferences = getE4PreferenceStore(); + return preferences != null ? preferences.get(PreferenceConstants.E4_THEME_ID, null) : null; + } + + /** + * Get editors preferences store + * + * @return preferences store + */ + @Nullable + public static IEclipsePreferences getEditorsPreferenceStore() { + return InstanceScope.INSTANCE.getNode(EDITORS_PREFERENCE_NAME); + } + + /** + * Get TM4E preferences store + * + * @return preferences store + */ + @Nullable + public static IPreferenceStore getTM4EPreferencesStore() { + final var plugin = TMUIPlugin.getDefault(); + return plugin == null ? null : plugin.getPreferenceStore(); + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/utils/package-info.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/utils/package-info.java new file mode 100644 index 000000000..e67631051 --- /dev/null +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/utils/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.ui.internal.utils; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ColumnSelectionAdapter.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ColumnSelectionAdapter.java index 2cef14c01..aeb2e81b5 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ColumnSelectionAdapter.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ColumnSelectionAdapter.java @@ -1,47 +1,48 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.widgets; - -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; - -/** - * Sort the selected column and refresh the viewer. - * - */ -public class ColumnSelectionAdapter extends SelectionAdapter { - - private final TableColumn fTableColumn; - private final TableViewer tableViewer; - private final int fColumnIndex; - private final ColumnViewerComparator viewerComparator; - - public ColumnSelectionAdapter(TableColumn column, TableViewer tableViewer, int index, ColumnViewerComparator vc) { - fTableColumn = column; - this.tableViewer = tableViewer; - fColumnIndex = index; - viewerComparator = vc; - } - - @Override - public void widgetSelected(SelectionEvent e) { - viewerComparator.setColumn(fColumnIndex); - int dir = viewerComparator.getDirection(); - Table table = tableViewer.getTable(); - table.setSortDirection(dir); - table.setSortColumn(fTableColumn); - tableViewer.refresh(); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.widgets; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; + +/** + * Sort the selected column and refresh the viewer. + * + */ +public final class ColumnSelectionAdapter extends SelectionAdapter { + + private final TableColumn fTableColumn; + private final TableViewer tableViewer; + private final int fColumnIndex; + private final ColumnViewerComparator viewerComparator; + + public ColumnSelectionAdapter(final TableColumn column, final TableViewer tableViewer, final int index, final ColumnViewerComparator vc) { + fTableColumn = column; + this.tableViewer = tableViewer; + fColumnIndex = index; + viewerComparator = vc; + } + + @Override + public void widgetSelected(@Nullable final SelectionEvent e) { + viewerComparator.setColumn(fColumnIndex); + final int dir = viewerComparator.getDirection(); + final Table table = tableViewer.getTable(); + table.setSortDirection(dir); + table.setSortColumn(fTableColumn); + tableViewer.refresh(); + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ColumnViewerComparator.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ColumnViewerComparator.java index d292b4268..856aa7413 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ColumnViewerComparator.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ColumnViewerComparator.java @@ -1,76 +1,71 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.widgets; - -import org.eclipse.jface.viewers.IBaseLabelProvider; -import org.eclipse.jface.viewers.ITableLabelProvider; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerComparator; -import org.eclipse.swt.SWT; - -/** - * Viewer compoarator which sort a given column. - * - */ -public class ColumnViewerComparator extends ViewerComparator { - - private int fSortColumn; - - private int fSortOrder; // 1 = asc, -1 = desc - - public ColumnViewerComparator() { - fSortColumn = 0; - fSortOrder = 1; - } - - /** - * Returns the {@linkplain SWT} style constant for the sort direction. - * - * @return {@link SWT#DOWN} for asc sorting, {@link SWT#UP} otherwise - */ - public int getDirection() { - return fSortOrder == 1 ? SWT.DOWN : SWT.UP; - } - - /** - * Sets the sort column. If the newly set sort column equals the previous - * set sort column, the sort direction changes. - * - * @param column - * New sort column - */ - public void setColumn(int column) { - if (column == fSortColumn) { - fSortOrder *= -1; - } else { - fSortColumn = column; - fSortOrder = 1; - } - } - - @Override - public int compare(Viewer viewer, Object e1, Object e2) { - - if (viewer instanceof TableViewer) { - IBaseLabelProvider baseLabel = ((TableViewer) viewer).getLabelProvider(); - - String left = ((ITableLabelProvider) baseLabel).getColumnText(e1, fSortColumn); - String right = ((ITableLabelProvider) baseLabel).getColumnText(e2, fSortColumn); - int sortResult = getComparator().compare(left != null ? left : "", right != null ? right : ""); - return sortResult * fSortOrder; - } - - return super.compare(viewer, e1, e2); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.widgets; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.swt.SWT; + +/** + * Viewer compoarator which sort a given column. + * + */ +public final class ColumnViewerComparator extends ViewerComparator { + + private int fSortColumn = 0; + private int fSortOrder = 1; // 1 = asc, -1 = desc + + /** + * Returns the {@linkplain SWT} style constant for the sort direction. + * + * @return {@link SWT#DOWN} for asc sorting, {@link SWT#UP} otherwise + */ + public int getDirection() { + return fSortOrder == 1 ? SWT.DOWN : SWT.UP; + } + + /** + * Sets the sort column. If the newly set sort column equals the previous + * set sort column, the sort direction changes. + * + * @param column + * New sort column + */ + public void setColumn(final int column) { + if (column == fSortColumn) { + fSortOrder *= -1; + } else { + fSortColumn = column; + fSortOrder = 1; + } + } + + @Override + public int compare(@Nullable final Viewer viewer, @Nullable final Object e1, @Nullable final Object e2) { + + if (viewer instanceof TableViewer) { + final IBaseLabelProvider baseLabel = ((TableViewer) viewer).getLabelProvider(); + + final String left = ((ITableLabelProvider) baseLabel).getColumnText(e1, fSortColumn); + final String right = ((ITableLabelProvider) baseLabel).getColumnText(e2, fSortColumn); + final int sortResult = getComparator().compare(left != null ? left : "", right != null ? right : ""); + return sortResult * fSortOrder; + } + + return super.compare(viewer, e1, e2); + } + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ContentTypeLabelProvider.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ContentTypeLabelProvider.java index 878513688..f3268f135 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ContentTypeLabelProvider.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ContentTypeLabelProvider.java @@ -1,49 +1,60 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.widgets; - -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.jface.viewers.ITableLabelProvider; -import org.eclipse.jface.viewers.LabelProvider; -import org.eclipse.swt.graphics.Image; - -/** - * Label provider for {@link IContentType}. - */ -public class ContentTypeLabelProvider extends LabelProvider implements ITableLabelProvider { - - @Override - public Image getColumnImage(Object element, int columnIndex) { - return null; - } - - @Override - public String getText(Object element) { - return getColumnText(element, 0); - } - - @Override - public String getColumnText(Object element, int columnIndex) { - String contentTypeId = (String) element; - switch (columnIndex) { - case 0: - IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeId); - if (contentType == null) { - return contentTypeId; - } - return contentType.getName() + " (" + contentType.getId() + ")"; - default: - return ""; //$NON-NLS-1$ - } - } + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.widgets; + +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; + +/** + * Label provider for {@link IContentType}. + */ +public final class ContentTypeLabelProvider extends LabelProvider implements ITableLabelProvider { + + @Nullable + @Override + public Image getColumnImage(@Nullable final Object element, final int columnIndex) { + return null; + } + + @Nullable + @Override + public String getText(@Nullable final Object element) { + return getColumnText(element, 0); + } + + @Nullable + @Override + public String getColumnText(@Nullable final Object element, final int columnIndex) { + switch (columnIndex) { + case 0: + IContentType contentType = null; + if(element instanceof IContentType) { + contentType = (IContentType) element; + } else if(element instanceof String) { + final String contentTypeId = (String) element; + contentType = Platform.getContentTypeManager().getContentType(contentTypeId); + if (contentType == null) { + return contentTypeId; + } + } else { + return ""; //$NON-NLS-1$ + } + return contentType.getName() + " (" + contentType.getId() + ")"; + default: + return ""; //$NON-NLS-1$ + } + } } \ No newline at end of file diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ContentTypesBindingWidget.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ContentTypesBindingWidget.java index 93df342d9..67dd34003 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ContentTypesBindingWidget.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ContentTypesBindingWidget.java @@ -1,34 +1,34 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.widgets; - -import org.eclipse.jface.viewers.ArrayContentProvider; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.tm4e.ui.internal.TMUIMessages; - -/** - * Widget which displays content type list on the ledt and "New", "Remove" - * buttons on the right. - * - */ -public class ContentTypesBindingWidget extends TableAndButtonsWidget { - - public ContentTypesBindingWidget(Composite parent, int style) { - super(parent, style, TMUIMessages.ContentTypesBindingWidget_description); - super.setContentProvider(ArrayContentProvider.getInstance()); - super.setLabelProvider(new ContentTypeLabelProvider()); - } - - @Override - protected void createButtons(Composite parent) { - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.widgets; + +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.tm4e.ui.internal.TMUIMessages; + +/** + * Widget which displays content type list on the ledt and "New", "Remove" + * buttons on the right. + * + */ +public final class ContentTypesBindingWidget extends TableAndButtonsWidget { + + public ContentTypesBindingWidget(final Composite parent, final int style) { + super(parent, style, TMUIMessages.ContentTypesBindingWidget_description); + super.setContentProvider(ArrayContentProvider.getInstance()); + super.setLabelProvider(new ContentTypeLabelProvider()); + } + + @Override + protected void createButtons(final Composite parent) { + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/GrammarDefinitionContentProvider.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/GrammarDefinitionContentProvider.java index c9163f515..a47245472 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/GrammarDefinitionContentProvider.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/GrammarDefinitionContentProvider.java @@ -1,41 +1,46 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.widgets; - -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.tm4e.registry.IGrammarRegistryManager; - -/** - * A content provider for the template grammar page's table viewer. - * - */ -public class GrammarDefinitionContentProvider implements IStructuredContentProvider { - - private IGrammarRegistryManager registry; - - @Override - public Object[] getElements(Object input) { - return registry.getDefinitions(); - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - registry = (IGrammarRegistryManager) newInput; - } - - @Override - public void dispose() { - registry = null; - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.widgets; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.tm4e.registry.IGrammarRegistryManager; + +/** + * A content provider for the template grammar page's table viewer. + * + */ +public final class GrammarDefinitionContentProvider implements IStructuredContentProvider { + @Nullable + private IGrammarRegistryManager registry; + + @Override + public Object @Nullable [] getElements(@Nullable final Object input) { + final var registry = this.registry; + if (registry == null) + return null; + return registry.getDefinitions(); + } + + @Override + public void inputChanged(@Nullable final Viewer viewer, @Nullable final Object oldInput, + @Nullable final Object newInput) { + registry = (IGrammarRegistryManager) newInput; + } + + @Override + public void dispose() { + registry = null; + } + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/GrammarDefinitionLabelProvider.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/GrammarDefinitionLabelProvider.java index 3d99b94b1..d0d314d46 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/GrammarDefinitionLabelProvider.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/GrammarDefinitionLabelProvider.java @@ -1,49 +1,55 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.widgets; - -import org.eclipse.jface.viewers.ITableLabelProvider; -import org.eclipse.jface.viewers.LabelProvider; -import org.eclipse.swt.graphics.Image; -import org.eclipse.tm4e.registry.IGrammarDefinition; - -/** - * Label provider for grammar definition. - */ -public class GrammarDefinitionLabelProvider extends LabelProvider implements ITableLabelProvider { - - @Override - public Image getColumnImage(Object element, int columnIndex) { - return null; - } - - @Override - public String getText(Object element) { - return getColumnText(element, 0); - } - - @Override - public String getColumnText(Object element, int columnIndex) { - IGrammarDefinition definition = (IGrammarDefinition) element; - - switch (columnIndex) { - case 0: - return definition.getScopeName(); - case 1: - return definition.getPath(); - case 2: - return definition.getPluginId(); - default: - return ""; //$NON-NLS-1$ - } - } + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.widgets; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tm4e.registry.IGrammarDefinition; + +/** + * Label provider for grammar definition. + */ +public final class GrammarDefinitionLabelProvider extends LabelProvider implements ITableLabelProvider { + @Nullable + @Override + public Image getColumnImage(@Nullable final Object element, final int columnIndex) { + return null; + } + + @Nullable + @Override + public String getText(@Nullable final Object element) { + return getColumnText(element, 0); + } + + @Nullable + @Override + public String getColumnText(@Nullable final Object element, final int columnIndex) { + if (element == null) + return ""; + + final IGrammarDefinition definition = (IGrammarDefinition) element; + + switch (columnIndex) { + case 0: + return definition.getScopeName(); + case 1: + return definition.getPath(); + case 2: + return definition.getPluginId(); + default: + return ""; //$NON-NLS-1$ + } + } } \ No newline at end of file diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/GrammarInfoWidget.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/GrammarInfoWidget.java index 8dee3b007..7082bb38b 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/GrammarInfoWidget.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/GrammarInfoWidget.java @@ -1,102 +1,99 @@ -/** - * Copyright (c) 2015-2019 Angelo ZERR. +/** + * Copyright (c) 2015-2019 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - * Pierre-Yves B. - Issue #221 NullPointerException when retrieving fileTypes - */ -package org.eclipse.tm4e.ui.internal.widgets; - -import java.util.Collection; -import java.util.stream.Collectors; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; -import org.eclipse.tm4e.core.grammar.IGrammar; -import org.eclipse.tm4e.ui.internal.TMUIMessages; - -/** - * - * Widget which display grammar information like name, scope, and file types. - */ -public class GrammarInfoWidget extends Composite { - - private Text nameText; - private Text scopeNameText; - private Text fileTypesText; - - public GrammarInfoWidget(Composite parent, int style) { - super(parent, style); - GridLayout layout = new GridLayout(); - layout.marginHeight = 0; - layout.marginWidth = 0; - layout.marginLeft = 0; - layout.marginRight = 0; - super.setLayout(layout); - super.setLayoutData(new GridData(GridData.FILL_BOTH)); - createUI(this); - } - - private void createUI(Composite ancestor) { - Composite parent = new Composite(ancestor, SWT.NONE); - GridLayout layout = new GridLayout(2, false); - layout.marginHeight = 0; - layout.marginWidth = 0; - layout.marginLeft = 0; - layout.marginRight = 0; - parent.setLayout(layout); - parent.setLayoutData(new GridData(GridData.FILL_BOTH)); - - Label grammarNameLabel = new Label(parent, SWT.NONE); - grammarNameLabel.setText(TMUIMessages.GrammarInfoWidget_name_text); - nameText = new Text(parent, SWT.BORDER | SWT.READ_ONLY); - nameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - Label grammarScopeNameLabel = new Label(parent, SWT.NONE); - grammarScopeNameLabel.setText(TMUIMessages.GrammarInfoWidget_scopeName_text); - scopeNameText = new Text(parent, SWT.BORDER | SWT.READ_ONLY); - scopeNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - Label grammarFileTypesLabel = new Label(parent, SWT.NONE); - grammarFileTypesLabel.setText(TMUIMessages.GrammarInfoWidget_fileTypes_text); - fileTypesText = new Text(parent, SWT.BORDER | SWT.READ_ONLY); - fileTypesText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - } - - public void refresh(IGrammar grammar) { - if (grammar == null) { - nameText.setText(""); - scopeNameText.setText(""); - fileTypesText.setText(""); - } else { - String name = grammar.getName(); - nameText.setText(name != null ? name : ""); - String scope = grammar.getScopeName(); - scopeNameText.setText(scope != null ? scope : ""); - Collection fileTypes = grammar.getFileTypes(); - String types = fileTypes.stream().map(Object::toString).collect(Collectors.joining(",")); - fileTypesText.setText(types); - } - } - - public Text getGrammarNameText() { - return nameText; - } - - public Text getScopeNameText() { - return scopeNameText; - } - - public Text getFileTypesText() { - return fileTypesText; - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + * Pierre-Yves B. - Issue #221 NullPointerException when retrieving fileTypes + */ +package org.eclipse.tm4e.ui.internal.widgets; + +import java.util.Collection; +import java.util.stream.Collectors; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.tm4e.core.grammar.IGrammar; +import org.eclipse.tm4e.ui.internal.TMUIMessages; + +/** + * Widget which display grammar information like name, scope, and file types. + */ +public final class GrammarInfoWidget extends Composite { + + private Text nameText; + private Text scopeNameText; + private Text fileTypesText; + + public GrammarInfoWidget(final Composite parent, final int style) { + super(parent, style); + final GridLayout layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + layout.marginLeft = 0; + layout.marginRight = 0; + super.setLayout(layout); + super.setLayoutData(new GridData(GridData.FILL_BOTH)); + + final Composite container = new Composite(this, SWT.NONE); + final GridLayout containerLayout = new GridLayout(2, false); + containerLayout.marginHeight = 0; + containerLayout.marginWidth = 0; + containerLayout.marginLeft = 0; + containerLayout.marginRight = 0; + container.setLayout(containerLayout); + container.setLayoutData(new GridData(GridData.FILL_BOTH)); + + final Label grammarNameLabel = new Label(container, SWT.NONE); + grammarNameLabel.setText(TMUIMessages.GrammarInfoWidget_name_text); + nameText = new Text(container, SWT.BORDER | SWT.READ_ONLY); + nameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + final Label grammarScopeNameLabel = new Label(container, SWT.NONE); + grammarScopeNameLabel.setText(TMUIMessages.GrammarInfoWidget_scopeName_text); + scopeNameText = new Text(container, SWT.BORDER | SWT.READ_ONLY); + scopeNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + final Label grammarFileTypesLabel = new Label(container, SWT.NONE); + grammarFileTypesLabel.setText(TMUIMessages.GrammarInfoWidget_fileTypes_text); + fileTypesText = new Text(container, SWT.BORDER | SWT.READ_ONLY); + fileTypesText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + } + + public void refresh(@Nullable final IGrammar grammar) { + if (grammar == null) { + nameText.setText(""); + scopeNameText.setText(""); + fileTypesText.setText(""); + } else { + final String name = grammar.getName(); + nameText.setText(name != null ? name : ""); + final String scope = grammar.getScopeName(); + scopeNameText.setText(scope); + final Collection fileTypes = grammar.getFileTypes(); + final String types = fileTypes.stream().map(Object::toString).collect(Collectors.joining(",")); + fileTypesText.setText(types); + } + } + + public Text getGrammarNameText() { + return nameText; + } + + public Text getScopeNameText() { + return scopeNameText; + } + + public Text getFileTypesText() { + return fileTypesText; + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/TMViewer.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/TMViewer.java index 1dbd8cc4a..dc2453aaf 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/TMViewer.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/TMViewer.java @@ -1,84 +1,76 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.widgets; - -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.jface.text.Document; -import org.eclipse.jface.text.presentation.IPresentationReconciler; -import org.eclipse.jface.text.source.IOverviewRuler; -import org.eclipse.jface.text.source.ISourceViewer; -import org.eclipse.jface.text.source.IVerticalRuler; -import org.eclipse.jface.text.source.SourceViewer; -import org.eclipse.jface.text.source.SourceViewerConfiguration; -import org.eclipse.swt.custom.StyledText; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.tm4e.core.grammar.IGrammar; -import org.eclipse.tm4e.ui.text.TMPresentationReconciler; -import org.eclipse.tm4e.ui.themes.ITheme; - -/** - * Simple TextMate Viewer. - * - */ -public class TMViewer extends SourceViewer { - - private TMPresentationReconciler reconciler; - - public TMViewer(Composite parent, IVerticalRuler ruler, int styles) { - super(parent, ruler, styles); - init(); - } - - public TMViewer(Composite parent, IVerticalRuler verticalRuler, IOverviewRuler overviewRuler, - boolean showAnnotationsOverview, int styles) { - super(parent, verticalRuler, overviewRuler, showAnnotationsOverview, styles); - init(); - } - - private void init() { - this.reconciler = new TMPresentationReconciler(); - SourceViewerConfiguration configuration = new TMSourceViewerConfiguration(); - this.configure(configuration); - } - - private class TMSourceViewerConfiguration extends SourceViewerConfiguration { - - @Override - public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) { - return reconciler; - } - - } - - public void setGrammar(IGrammar grammar) { - reconciler.setGrammar(grammar); - if (getDocument() == null) { - super.setDocument(new Document()); - } - } - - public void setTheme(ITheme theme) { - reconciler.setTheme(theme); - StyledText styledText = getTextWidget(); - styledText.setForeground(null); - styledText.setBackground(null); - theme.initializeViewerColors(styledText); - getTextWidget().setFont(JFaceResources.getTextFont()); - } - - public void setText(String text) { - if (getDocument() == null) { - super.setDocument(new Document()); - } - getDocument().set(text); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.widgets; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.source.IOverviewRuler; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.IVerticalRuler; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.tm4e.core.grammar.IGrammar; +import org.eclipse.tm4e.ui.text.TMPresentationReconciler; +import org.eclipse.tm4e.ui.themes.ITheme; + +/** + * Simple TextMate Viewer. + */ +public final class TMViewer extends SourceViewer { + + private final TMPresentationReconciler reconciler = new TMPresentationReconciler(); + + public TMViewer(final Composite parent, final IVerticalRuler ruler, final int styles) { + this(parent, ruler, null, false, styles); + } + + public TMViewer(final Composite parent, @Nullable final IVerticalRuler verticalRuler, + @Nullable final IOverviewRuler overviewRuler, + final boolean showAnnotationsOverview, final int styles) { + super(parent, verticalRuler, overviewRuler, showAnnotationsOverview, styles); + configure(new TMSourceViewerConfiguration()); + } + + private final class TMSourceViewerConfiguration extends SourceViewerConfiguration { + @Override + public IPresentationReconciler getPresentationReconciler(@Nullable final ISourceViewer sourceViewer) { + return reconciler; + } + } + + public void setGrammar(@Nullable final IGrammar grammar) { + reconciler.setGrammar(grammar); + if (getDocument() == null) { + super.setDocument(new Document()); + } + } + + public void setTheme(final ITheme theme) { + reconciler.setTheme(theme); + final StyledText styledText = getTextWidget(); + styledText.setForeground(null); + styledText.setBackground(null); + theme.initializeViewerColors(styledText); + getTextWidget().setFont(JFaceResources.getTextFont()); + } + + public void setText(final String text) { + if (getDocument() == null) { + super.setDocument(new Document()); + } + getDocument().set(text); + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/TableAndButtonsWidget.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/TableAndButtonsWidget.java index 975ae0cfc..f52c382e7 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/TableAndButtonsWidget.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/TableAndButtonsWidget.java @@ -1,123 +1,126 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.widgets; - -import org.eclipse.jface.viewers.IBaseLabelProvider; -import org.eclipse.jface.viewers.IContentProvider; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Table; - -/** - * Widget which display a table on the left and buttons on the right. - * - */ -public abstract class TableAndButtonsWidget extends Composite { - - private TableViewer viewer; - - public TableAndButtonsWidget(Composite parent, int style, String title) { - super(parent, style); - GridLayout layout = new GridLayout(); - layout.marginHeight = 0; - layout.marginWidth = 0; - layout.marginLeft = 0; - layout.marginRight = 0; - super.setLayout(layout); - createUI(title, this); - } - - private void createUI(String title, Composite ancestor) { - Composite parent = new Composite(ancestor, SWT.NONE); - GridLayout layout = new GridLayout(2, false); - layout.marginHeight = 0; - layout.marginWidth = 0; - layout.marginLeft = 0; - layout.marginRight = 0; - parent.setLayout(layout); - parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - // Title - createTitle(title, parent); - - // Table - createTable(parent); - - // Buttons - Composite buttonsComposite = new Composite(parent, SWT.NONE); - layout = new GridLayout(); - layout.marginHeight = 0; - layout.marginWidth = 0; - layout.marginLeft = 0; - layout.marginRight = 0; - buttonsComposite.setLayout(layout); - buttonsComposite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_VERTICAL)); - createButtons(buttonsComposite); - } - - protected abstract void createButtons(Composite parent); - - private void createTitle(String title, Composite ancestor) { - if (title == null) { - return; - } - Label label = new Label(ancestor, SWT.NONE); - label.setText(title); - GridData data = new GridData(GridData.FILL_HORIZONTAL); - data.horizontalSpan = 2; - label.setLayoutData(data); - } - - private void createTable(Composite parent) { - Table table = new Table(parent, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL); - table.setHeaderVisible(false); - table.setLinesVisible(false); - - viewer = new TableViewer(table); - table.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - } - - public void setInput(Object input) { - viewer.setInput(input); - } - - public TableViewer getViewer() { - return viewer; - } - - public void setLabelProvider(IBaseLabelProvider labelProvider) { - viewer.setLabelProvider(labelProvider); - } - - public void setContentProvider(IContentProvider provider) { - viewer.setContentProvider(provider); - } - - public void addSelectionChangedListener(ISelectionChangedListener listener) { - viewer.addSelectionChangedListener(listener); - } - - public void setSelection(IStructuredSelection selection) { - viewer.setSelection(selection); - } - - public IStructuredSelection getSelection() { - return viewer.getStructuredSelection(); - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.widgets; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; + +/** + * Widget which display a table on the left and buttons on the right. + * + */ +public abstract class TableAndButtonsWidget extends Composite { + + @Nullable + private TableViewer viewer; + + protected TableAndButtonsWidget(final Composite parent, final int style, final String title) { + super(parent, style); + final GridLayout layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + layout.marginLeft = 0; + layout.marginRight = 0; + super.setLayout(layout); + createUI(title, this); + } + + private void createUI(final String title, final Composite ancestor) { + final Composite parent = new Composite(ancestor, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + layout.marginHeight = 0; + layout.marginWidth = 0; + layout.marginLeft = 0; + layout.marginRight = 0; + parent.setLayout(layout); + parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + // Title + createTitle(title, parent); + + // Table + createTable(parent); + + // Buttons + final Composite buttonsComposite = new Composite(parent, SWT.NONE); + layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + layout.marginLeft = 0; + layout.marginRight = 0; + buttonsComposite.setLayout(layout); + buttonsComposite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_VERTICAL)); + createButtons(buttonsComposite); + } + + protected abstract void createButtons(Composite parent); + + private void createTitle(final String title, final Composite ancestor) { + final Label label = new Label(ancestor, SWT.NONE); + label.setText(title); + final GridData data = new GridData(GridData.FILL_HORIZONTAL); + data.horizontalSpan = 2; + label.setLayoutData(data); + } + + private void createTable(final Composite parent) { + final Table table = new Table(parent, + SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL); + table.setHeaderVisible(false); + table.setLinesVisible(false); + + viewer = new TableViewer(table); + table.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + } + + public void setInput(@Nullable final Object input) { + castNonNull(viewer).setInput(input); + } + + @Nullable + public TableViewer getViewer() { + return viewer; + } + + public void setLabelProvider(final IBaseLabelProvider labelProvider) { + castNonNull(viewer).setLabelProvider(labelProvider); + } + + public void setContentProvider(final IContentProvider provider) { + castNonNull(viewer).setContentProvider(provider); + } + + public void addSelectionChangedListener(final ISelectionChangedListener listener) { + castNonNull(viewer).addSelectionChangedListener(listener); + } + + public void setSelection(final IStructuredSelection selection) { + castNonNull(viewer).setSelection(selection); + } + + public IStructuredSelection getSelection() { + return castNonNull(viewer).getStructuredSelection(); + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ThemeAssociationLabelProvider.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ThemeAssociationLabelProvider.java index c31673bf4..95f7ee0da 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ThemeAssociationLabelProvider.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ThemeAssociationLabelProvider.java @@ -1,61 +1,69 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.widgets; - -import org.eclipse.jface.viewers.ITableLabelProvider; -import org.eclipse.jface.viewers.LabelProvider; -import org.eclipse.osgi.util.NLS; -import org.eclipse.swt.graphics.Image; -import org.eclipse.tm4e.ui.TMUIPlugin; -import org.eclipse.tm4e.ui.internal.TMUIMessages; -import org.eclipse.tm4e.ui.themes.ITheme; -import org.eclipse.tm4e.ui.themes.IThemeAssociation; -import org.eclipse.tm4e.ui.themes.IThemeManager; - -/** - * Label provider for TextMate theme association. - */ -public class ThemeAssociationLabelProvider extends LabelProvider implements ITableLabelProvider { - - @Override - public Image getColumnImage(Object element, int columnIndex) { - return null; - } - - @Override - public String getText(Object element) { - return getColumnText(element, 0); - } - - @Override - public String getColumnText(Object element, int columnIndex) { - IThemeAssociation association = (IThemeAssociation) element; - switch (columnIndex) { - case 0: - ITheme theme = getTheme(association); - String themeName = theme != null ? theme.getName() : association.getThemeId(); - if (association.isWhenDark()) { - return NLS.bind(TMUIMessages.ThemeAssociationLabelProvider_dark, themeName); - } - return NLS.bind(TMUIMessages.ThemeAssociationLabelProvider_light, themeName); - default: - return ""; //$NON-NLS-1$ - } - } - - private ITheme getTheme(IThemeAssociation association) { - String themeId = association.getThemeId(); - IThemeManager themeManager = TMUIPlugin.getThemeManager(); - return themeManager.getThemeById(themeId); - } - + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.widgets; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tm4e.ui.TMUIPlugin; +import org.eclipse.tm4e.ui.internal.TMUIMessages; +import org.eclipse.tm4e.ui.themes.ITheme; +import org.eclipse.tm4e.ui.themes.IThemeAssociation; +import org.eclipse.tm4e.ui.themes.IThemeManager; + +/** + * Label provider for TextMate theme association. + */ +public final class ThemeAssociationLabelProvider extends LabelProvider implements ITableLabelProvider { + + @Nullable + @Override + public Image getColumnImage(@Nullable final Object element, final int columnIndex) { + return null; + } + + @Nullable + @Override + public String getText(@Nullable final Object element) { + return getColumnText(element, 0); + } + + @Nullable + @Override + public String getColumnText(@Nullable final Object element, final int columnIndex) { + if (element == null) + return ""; + + final IThemeAssociation association = (IThemeAssociation) element; + switch (columnIndex) { + case 0: + final ITheme theme = getTheme(association); + final String themeName = theme != null ? theme.getName() : association.getThemeId(); + if (association.isWhenDark()) { + return NLS.bind(TMUIMessages.ThemeAssociationLabelProvider_dark, themeName); + } + return NLS.bind(TMUIMessages.ThemeAssociationLabelProvider_light, themeName); + default: + return ""; //$NON-NLS-1$ + } + } + + @Nullable + private ITheme getTheme(final IThemeAssociation association) { + final String themeId = association.getThemeId(); + final IThemeManager themeManager = TMUIPlugin.getThemeManager(); + return themeManager.getThemeById(themeId); + } + } \ No newline at end of file diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ThemeAssociationsWidget.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ThemeAssociationsWidget.java index 20b570c99..9698c74df 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ThemeAssociationsWidget.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ThemeAssociationsWidget.java @@ -1,120 +1,129 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.widgets; - -import java.util.Iterator; - -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.ArrayContentProvider; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.window.Window; -import org.eclipse.jface.wizard.WizardDialog; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.tm4e.registry.IGrammarDefinition; -import org.eclipse.tm4e.ui.internal.TMUIMessages; -import org.eclipse.tm4e.ui.internal.wizards.CreateThemeAssociationWizard; -import org.eclipse.tm4e.ui.themes.IThemeAssociation; -import org.eclipse.tm4e.ui.themes.IThemeManager; - -/** - * Widget which displays theme associations list on the left and "New", "Remove" - * buttons on the right. - * - */ -public class ThemeAssociationsWidget extends TableAndButtonsWidget { - - private IThemeManager themeManager; - - private Button editButton; - private Button removeButton; - - private IGrammarDefinition definition; - - public ThemeAssociationsWidget(IThemeManager themeManager, Composite parent, int style) { - super(parent, style, TMUIMessages.ThemeAssociationsWidget_description); - this.themeManager = themeManager; - super.setContentProvider(ArrayContentProvider.getInstance()); - super.setLabelProvider(new ThemeAssociationLabelProvider()); - } - - @Override - protected void createButtons(Composite parent) { - editButton = new Button(parent, SWT.PUSH); - editButton.setText(TMUIMessages.Button_edit); - editButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - editButton.addListener(SWT.Selection, (e) -> { - // Open the wizard to create association between theme and grammar. - CreateThemeAssociationWizard wizard = new CreateThemeAssociationWizard(false); - wizard.setInitialDefinition(definition); - IStructuredSelection selection = super.getSelection(); - wizard.setInitialAssociation(selection.isEmpty() ? null : (IThemeAssociation) selection.getFirstElement()); - wizard.setThemeManager(themeManager); - WizardDialog dialog = new WizardDialog(getShell(), wizard); - if (dialog.open() == Window.OK) { - IThemeAssociation association = wizard.getCreatedThemeAssociation(); - refresh(association); - } - }); - editButton.setEnabled(false); - - removeButton = new Button(parent, SWT.PUSH); - removeButton.setText(TMUIMessages.Button_remove); - removeButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - removeButton.addListener(SWT.Selection, (e) -> { - - if (MessageDialog.openConfirm(getShell(), TMUIMessages.ThemeAssociationsWidget_remove_dialog_title, - TMUIMessages.ThemeAssociationsWidget_remove_dialog_message)) { - IStructuredSelection selection = super.getSelection(); - Iterator it = selection.iterator(); - while (it.hasNext()) { - IThemeAssociation association = it.next(); - themeManager.unregisterThemeAssociation(association); - } - refresh(null); - } - - }); - removeButton.setEnabled(false); - } - - public Button getNewButton() { - return editButton; - } - - public Button getRemoveButton() { - return removeButton; - } - - public IThemeAssociation[] setGrammarDefinition(IGrammarDefinition definition) { - this.definition = definition; - return refresh(null); - } - - private IThemeAssociation[] refresh(IThemeAssociation association) { - IThemeAssociation[] themeAssociations = themeManager.getThemeAssociationsForScope(definition.getScopeName()); - // Refresh the list of associations - super.setInput(themeAssociations); - // Select the first of given association - if (association == null && themeAssociations != null && themeAssociations.length > 0) { - association = themeAssociations[0]; - } - if (association != null) { - super.setSelection(new StructuredSelection(association)); - } - return themeAssociations; - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.widgets; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import java.util.Iterator; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.tm4e.registry.IGrammarDefinition; +import org.eclipse.tm4e.ui.internal.TMUIMessages; +import org.eclipse.tm4e.ui.internal.wizards.CreateThemeAssociationWizard; +import org.eclipse.tm4e.ui.themes.IThemeAssociation; +import org.eclipse.tm4e.ui.themes.IThemeManager; + +/** + * Widget which displays theme associations list on the left and "New", "Remove" + * buttons on the right. + * + */ +public final class ThemeAssociationsWidget extends TableAndButtonsWidget { + + private final IThemeManager themeManager; + + @Nullable + private Button editButton; + @Nullable + private Button removeButton; + @Nullable + private IGrammarDefinition definition; + + public ThemeAssociationsWidget(final IThemeManager themeManager, final Composite parent, final int style) { + super(parent, style, TMUIMessages.ThemeAssociationsWidget_description); + this.themeManager = themeManager; + super.setContentProvider(ArrayContentProvider.getInstance()); + super.setLabelProvider(new ThemeAssociationLabelProvider()); + } + + @Override + protected void createButtons(final Composite parent) { + final var editButton = this.editButton = new Button(parent, SWT.PUSH); + editButton.setText(TMUIMessages.Button_edit); + editButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + editButton.addListener(SWT.Selection, e -> { + // Open the wizard to create association between theme and grammar. + final CreateThemeAssociationWizard wizard = new CreateThemeAssociationWizard(false); + wizard.setInitialDefinition(definition); + final IStructuredSelection selection = super.getSelection(); + wizard.setInitialAssociation(selection.isEmpty() ? null : (IThemeAssociation) selection.getFirstElement()); + wizard.setThemeManager(themeManager); + final WizardDialog dialog = new WizardDialog(getShell(), wizard); + if (dialog.open() == Window.OK) { + final IThemeAssociation association = wizard.getCreatedThemeAssociation(); + refresh(association); + } + }); + editButton.setEnabled(false); + + final var removeButton = this.removeButton = new Button(parent, SWT.PUSH); + removeButton.setText(TMUIMessages.Button_remove); + removeButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + removeButton.addListener(SWT.Selection, e -> { + if (MessageDialog.openConfirm(getShell(), TMUIMessages.ThemeAssociationsWidget_remove_dialog_title, + TMUIMessages.ThemeAssociationsWidget_remove_dialog_message)) { + final IStructuredSelection selection = super.getSelection(); + final Iterator it = selection.iterator(); + while (it.hasNext()) { + final IThemeAssociation association = it.next(); + themeManager.unregisterThemeAssociation(association); + } + refresh(null); + } + + }); + removeButton.setEnabled(false); + } + + public Button getNewButton() { + return castNonNull(editButton); + } + + public Button getRemoveButton() { + return castNonNull(removeButton); + } + + public IThemeAssociation[] setGrammarDefinition(final IGrammarDefinition definition) { + this.definition = definition; + return refresh(null); + } + + private IThemeAssociation[] refresh(@Nullable IThemeAssociation association) { + final var definition = this.definition; + if (definition == null) { + return new IThemeAssociation[0]; + } + final IThemeAssociation[] themeAssociations = themeManager + .getThemeAssociationsForScope(definition.getScopeName()); + // Refresh the list of associations + super.setInput(themeAssociations); + // Select the first of given association + if (association == null && themeAssociations.length > 0) { + association = themeAssociations[0]; + } + if (association != null) { + super.setSelection(new StructuredSelection(association)); + } + return themeAssociations; + } + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ThemeContentProvider.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ThemeContentProvider.java index 88929902a..4316c56e8 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ThemeContentProvider.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ThemeContentProvider.java @@ -1,41 +1,47 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.widgets; - -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.tm4e.ui.themes.IThemeManager; - -/** - * A content provider for the template theme page's table viewer. - * - */ -public class ThemeContentProvider implements IStructuredContentProvider { - - private IThemeManager registry; - - @Override - public Object[] getElements(Object input) { - return registry.getThemes(); - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - registry = (IThemeManager) newInput; - } - - @Override - public void dispose() { - registry = null; - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.widgets; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.tm4e.ui.themes.IThemeManager; + +/** + * A content provider for the template theme page's table viewer. + * + */ +public final class ThemeContentProvider implements IStructuredContentProvider { + + @Nullable + private IThemeManager registry; + + @Override + public Object @Nullable [] getElements(@Nullable final Object input) { + final var registry = this.registry; + if (registry == null) + return null; + return registry.getThemes(); + } + + @Override + public void inputChanged(@Nullable final Viewer viewer, @Nullable final Object oldInput, + @Nullable final Object newInput) { + registry = (IThemeManager) newInput; + } + + @Override + public void dispose() { + registry = null; + } + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ThemeLabelProvider.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ThemeLabelProvider.java index b46d57b8a..0154c4d1f 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ThemeLabelProvider.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/ThemeLabelProvider.java @@ -1,49 +1,57 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.widgets; - -import org.eclipse.jface.viewers.ITableLabelProvider; -import org.eclipse.jface.viewers.LabelProvider; -import org.eclipse.swt.graphics.Image; -import org.eclipse.tm4e.ui.themes.ITheme; - -/** - * Label provider for TextMate theme. - */ -public class ThemeLabelProvider extends LabelProvider implements ITableLabelProvider { - - @Override - public Image getColumnImage(Object element, int columnIndex) { - return null; - } - - @Override - public String getText(Object element) { - ITheme theme = (ITheme) element; - return theme.getName(); - } - - @Override - public String getColumnText(Object element, int columnIndex) { - ITheme theme = (ITheme) element; - switch (columnIndex) { - case 0: - return theme.getName(); - case 1: - return theme.getPath(); - case 2: - return theme.getPluginId(); - default: - return ""; //$NON-NLS-1$ - } - } + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.widgets; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tm4e.ui.themes.ITheme; + +/** + * Label provider for TextMate theme. + */ +public final class ThemeLabelProvider extends LabelProvider implements ITableLabelProvider { + + @Nullable + @Override + public Image getColumnImage(@Nullable final Object element, final int columnIndex) { + return null; + } + + @Nullable + @Override + public String getText(@Nullable final Object element) { + if (element == null) + return ""; + final ITheme theme = (ITheme) element; + return theme.getName(); + } + + @Nullable + @Override + public String getColumnText(@Nullable final Object element, final int columnIndex) { + if (element == null) + return ""; + final ITheme theme = (ITheme) element; + switch (columnIndex) { + case 0: + return theme.getName(); + case 1: + return theme.getPath(); + case 2: + return theme.getPluginId(); + default: + return ""; //$NON-NLS-1$ + } + } } \ No newline at end of file diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/package-info.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/package-info.java new file mode 100644 index 000000000..b08e26c4a --- /dev/null +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/widgets/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.ui.internal.widgets; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/AbstractWizardPage.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/AbstractWizardPage.java index a355fedb2..fbbce6fd8 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/AbstractWizardPage.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/AbstractWizardPage.java @@ -1,109 +1,114 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - * - */ -package org.eclipse.tm4e.ui.internal.wizards; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.jface.dialogs.DialogPage; -import org.eclipse.jface.dialogs.IMessageProvider; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.wizard.WizardPage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; - -/** - * Abstract class for wizard page. - * - */ -public abstract class AbstractWizardPage extends WizardPage implements Listener { - - protected AbstractWizardPage(String pageName) { - super(pageName); - } - - protected AbstractWizardPage(String pageName, String title, ImageDescriptor titleImage) { - super(pageName, title, titleImage); - } - - @Override - public final void createControl(Composite parent) { - initializeDialogUnits(parent); - // top level group - Composite topLevel = new Composite(parent, SWT.NONE); - topLevel.setLayout(new GridLayout()); - topLevel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL)); - topLevel.setFont(parent.getFont()); - - // Create Body UI - createBody(topLevel); - // initialize page with default values - initializeDefaultValues(); - // Validate page fields. -// validateAndUpdateStatus(null); - setControl(topLevel); - } - - @Override - public void handleEvent(Event event) { - validateAndUpdateStatus(event); - } - - private void validateAndUpdateStatus(Event event) { - IStatus status = validatePage(event); - statusChanged(status == null ? Status.OK_STATUS : status); - } - - public void statusChanged(IStatus status) { - setPageComplete(!status.matches(IStatus.ERROR)); - applyToStatusLine(this, status); - } - - /** - * Applies the status to the status line of a dialog page. - */ - private static void applyToStatusLine(DialogPage page, IStatus status) { - String message = Status.OK_STATUS.equals(status) ? null : status.getMessage(); - switch (status.getSeverity()) { - case IStatus.OK: - page.setMessage(message, IMessageProvider.NONE); - page.setErrorMessage(null); - break; - case IStatus.WARNING: - page.setMessage(message, IMessageProvider.WARNING); - page.setErrorMessage(null); - break; - case IStatus.INFO: - page.setMessage(message, IMessageProvider.INFORMATION); - page.setErrorMessage(null); - break; - default: - if (message != null && message.length() == 0) { - message = null; - } - page.setMessage(null); - page.setErrorMessage(message); - break; - } - } - - protected abstract void createBody(Composite parent); - - protected abstract void initializeDefaultValues(); - - protected abstract IStatus validatePage(Event event); - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + * + */ +package org.eclipse.tm4e.ui.internal.wizards; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.dialogs.DialogPage; +import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; + +/** + * Abstract class for wizard page. + * + */ +abstract class AbstractWizardPage extends WizardPage implements Listener { + + protected AbstractWizardPage(final String pageName) { + super(pageName); + } + + protected AbstractWizardPage(final String pageName, final String title, final ImageDescriptor titleImage) { + super(pageName, title, titleImage); + } + + @Override + public final void createControl(@Nullable final Composite parent) { + assert parent != null; + + initializeDialogUnits(parent); + // top level group + final Composite topLevel = new Composite(parent, SWT.NONE); + topLevel.setLayout(new GridLayout()); + topLevel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL)); + topLevel.setFont(parent.getFont()); + + // Create Body UI + createBody(topLevel); + // initialize page with default values + initializeDefaultValues(); + // Validate page fields. + // validateAndUpdateStatus(null); + setControl(topLevel); + } + + @Override + public void handleEvent(@Nullable final Event event) { + if (event != null) + validateAndUpdateStatus(event); + } + + private void validateAndUpdateStatus(final Event event) { + final IStatus status = validatePage(event); + statusChanged(status == null ? Status.OK_STATUS : status); + } + + void statusChanged(final IStatus status) { + setPageComplete(!status.matches(IStatus.ERROR)); + applyToStatusLine(this, status); + } + + /** + * Applies the status to the status line of a dialog page. + */ + private static void applyToStatusLine(final DialogPage page, final IStatus status) { + String message = Status.OK_STATUS.equals(status) ? null : status.getMessage(); + switch (status.getSeverity()) { + case IStatus.OK: + page.setMessage(message, IMessageProvider.NONE); + page.setErrorMessage(null); + break; + case IStatus.WARNING: + page.setMessage(message, IMessageProvider.WARNING); + page.setErrorMessage(null); + break; + case IStatus.INFO: + page.setMessage(message, IMessageProvider.INFORMATION); + page.setErrorMessage(null); + break; + default: + if (message != null && message.isEmpty()) { + message = null; + } + page.setMessage(null); + page.setErrorMessage(message); + break; + } + } + + protected abstract void createBody(Composite parent); + + protected abstract void initializeDefaultValues(); + + @Nullable + protected abstract IStatus validatePage(Event event); + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/CreateThemeAssociationWizard.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/CreateThemeAssociationWizard.java index d5580e88f..34d5f11ad 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/CreateThemeAssociationWizard.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/CreateThemeAssociationWizard.java @@ -1,92 +1,91 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.wizards; - -import org.eclipse.jface.wizard.Wizard; -import org.eclipse.tm4e.registry.IGrammarDefinition; -import org.eclipse.tm4e.ui.TMUIPlugin; -import org.eclipse.tm4e.ui.themes.IThemeAssociation; -import org.eclipse.tm4e.ui.themes.IThemeManager; -import org.osgi.service.prefs.BackingStoreException; - -/** - * Wizard to create association between grammar and theme. - * - */ -public class CreateThemeAssociationWizard extends Wizard { - - private CreateThemeAssociationWizardPage mainPage; - - private IThemeAssociation createdThemeAssociation; - - private IThemeManager themeManager; - - private final boolean save; - - private IGrammarDefinition initialDefinition; - - private IThemeAssociation initialAssociation; - - public CreateThemeAssociationWizard() { - this(true); - } - - public CreateThemeAssociationWizard(boolean save) { - this.save = save; - setThemeManager(TMUIPlugin.getThemeManager()); - } - - /** - * Set theme managerto use to add the created theme associations. - * - * @param themeManager - */ - public void setThemeManager(IThemeManager themeManager) { - this.themeManager = themeManager; - } - - @Override - public void addPages() { - mainPage = new CreateThemeAssociationWizardPage(initialDefinition, initialAssociation); - addPage(mainPage); - } - - @Override - public boolean performFinish() { - IThemeAssociation association = mainPage.getThemeAssociation(); - themeManager.registerThemeAssociation(association); - if (save) { - try { - themeManager.save(); - } catch (BackingStoreException e) { - e.printStackTrace(); - return false; - } - } - createdThemeAssociation = association; - return true; - } - - public IThemeAssociation getCreatedThemeAssociation() { - return createdThemeAssociation; - } - - public void setInitialDefinition(IGrammarDefinition definition) { - this.initialDefinition = definition; - } - - public void setInitialAssociation(IThemeAssociation association) { - this.initialAssociation = association; - - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.wizards; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.tm4e.registry.IGrammarDefinition; +import org.eclipse.tm4e.ui.TMUIPlugin; +import org.eclipse.tm4e.ui.themes.IThemeAssociation; +import org.eclipse.tm4e.ui.themes.IThemeManager; +import org.osgi.service.prefs.BackingStoreException; + +/** + * Wizard to create association between grammar and theme. + * + */ +public final class CreateThemeAssociationWizard extends Wizard { + + @Nullable + private CreateThemeAssociationWizardPage mainPage; + + @Nullable + private IThemeAssociation createdThemeAssociation; + + private IThemeManager themeManager = TMUIPlugin.getThemeManager(); + + private final boolean save; + + @Nullable + private IGrammarDefinition initialDefinition; + + @Nullable + private IThemeAssociation initialAssociation; + + public CreateThemeAssociationWizard(final boolean save) { + this.save = save; + } + + /** + * Set theme manager to use to add the created theme associations. + */ + public void setThemeManager(final IThemeManager themeManager) { + this.themeManager = themeManager; + } + + @Override + public void addPages() { + mainPage = new CreateThemeAssociationWizardPage(initialDefinition, initialAssociation); + addPage(mainPage); + } + + @Override + public boolean performFinish() { + final IThemeAssociation association = castNonNull(mainPage).getThemeAssociation(); + themeManager.registerThemeAssociation(association); + if (save) { + try { + themeManager.save(); + } catch (final BackingStoreException e) { + e.printStackTrace(); + return false; + } + } + createdThemeAssociation = association; + return true; + } + + @Nullable + public IThemeAssociation getCreatedThemeAssociation() { + return createdThemeAssociation; + } + + public void setInitialDefinition(@Nullable final IGrammarDefinition definition) { + this.initialDefinition = definition; + } + + public void setInitialAssociation(@Nullable final IThemeAssociation association) { + this.initialAssociation = association; + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/CreateThemeAssociationWizardPage.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/CreateThemeAssociationWizardPage.java index 14bb1b168..da0f35147 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/CreateThemeAssociationWizardPage.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/CreateThemeAssociationWizardPage.java @@ -1,131 +1,147 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.wizards; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.jface.viewers.ComboViewer; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Label; -import org.eclipse.tm4e.registry.IGrammarDefinition; -import org.eclipse.tm4e.registry.TMEclipseRegistryPlugin; -import org.eclipse.tm4e.ui.TMUIPlugin; -import org.eclipse.tm4e.ui.internal.TMUIMessages; -import org.eclipse.tm4e.ui.internal.widgets.GrammarDefinitionContentProvider; -import org.eclipse.tm4e.ui.internal.widgets.GrammarDefinitionLabelProvider; -import org.eclipse.tm4e.ui.internal.widgets.ThemeContentProvider; -import org.eclipse.tm4e.ui.internal.widgets.ThemeLabelProvider; -import org.eclipse.tm4e.ui.themes.ITheme; -import org.eclipse.tm4e.ui.themes.IThemeAssociation; -import org.eclipse.tm4e.ui.themes.ThemeAssociation; - -/** - * Wizard page to create association between grammar and theme. - * - */ -public class CreateThemeAssociationWizardPage extends AbstractWizardPage { - - private static final String PAGE_NAME = CreateThemeAssociationWizardPage.class.getName(); - - private ComboViewer themeViewer; - private ComboViewer grammarViewer; - private final IGrammarDefinition initialDefinition; - private final IThemeAssociation initialAssociation; - - private Button whenDarkButton; - - protected CreateThemeAssociationWizardPage(IGrammarDefinition initialDefinition, - IThemeAssociation initialAssociation) { - super(PAGE_NAME); - super.setTitle(TMUIMessages.CreateThemeAssociationWizardPage_title); - super.setDescription(TMUIMessages.CreateThemeAssociationWizardPage_description); - this.initialDefinition = initialDefinition; - this.initialAssociation = initialAssociation; - } - - @Override - protected void createBody(Composite ancestor) { - Composite parent = new Composite(ancestor, SWT.NONE); - parent.setFont(parent.getFont()); - parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - parent.setLayout(new GridLayout(4, false)); - - // TextMate theme - Label label = new Label(parent, SWT.NONE); - label.setText(TMUIMessages.CreateThemeAssociationWizardPage_theme_text); - themeViewer = new ComboViewer(parent); - themeViewer.setLabelProvider(new ThemeLabelProvider()); - themeViewer.setContentProvider(new ThemeContentProvider()); - themeViewer.setInput(TMUIPlugin.getThemeManager()); - themeViewer.getControl().setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - themeViewer.getControl().addListener(SWT.Selection, this); - - label = new Label(parent, SWT.NONE); - label.setText(TMUIMessages.CreateThemeAssociationWizardPage_grammar_text); - grammarViewer = new ComboViewer(parent); - grammarViewer.setLabelProvider(new GrammarDefinitionLabelProvider()); - grammarViewer.setContentProvider(new GrammarDefinitionContentProvider()); - grammarViewer.setInput(TMEclipseRegistryPlugin.getGrammarRegistryManager()); - grammarViewer.getControl().setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - grammarViewer.getControl().addListener(SWT.Selection, this); - - if (initialDefinition != null) { - grammarViewer.setSelection(new StructuredSelection(initialDefinition)); - } - - whenDarkButton = new Button(parent, SWT.CHECK); - whenDarkButton.setText(TMUIMessages.CreateThemeAssociationWizardPage_whenDark_text); - GridData data = new GridData(); - data.horizontalSpan = 4; - whenDarkButton.setLayoutData(data); - if (initialAssociation != null) { - ITheme selectedTheme = TMUIPlugin.getThemeManager().getThemeById(initialAssociation.getThemeId()); - if (selectedTheme != null) { - themeViewer.setSelection(new StructuredSelection(selectedTheme)); - } - whenDarkButton.setSelection(initialAssociation.isWhenDark()); - } - } - - @Override - protected void initializeDefaultValues() { - setPageComplete(false); - } - - @Override - protected IStatus validatePage(Event event) { - if (themeViewer.getSelection().isEmpty()) { - return new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, - TMUIMessages.CreateThemeAssociationWizardPage_theme_error_required); - } - if (grammarViewer.getSelection().isEmpty()) { - return new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, - TMUIMessages.CreateThemeAssociationWizardPage_grammar_error_required); - } - return null; - } - - public IThemeAssociation getThemeAssociation() { - String themeId = ((ITheme) themeViewer.getStructuredSelection().getFirstElement()).getId(); - String scopeName = ((IGrammarDefinition) grammarViewer.getStructuredSelection().getFirstElement()) - .getScopeName(); - boolean whenDark = whenDarkButton.getSelection(); - return new ThemeAssociation(themeId, scopeName, whenDark); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.wizards; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.tm4e.registry.IGrammarDefinition; +import org.eclipse.tm4e.registry.TMEclipseRegistryPlugin; +import org.eclipse.tm4e.ui.TMUIPlugin; +import org.eclipse.tm4e.ui.internal.TMUIMessages; +import org.eclipse.tm4e.ui.internal.widgets.GrammarDefinitionContentProvider; +import org.eclipse.tm4e.ui.internal.widgets.GrammarDefinitionLabelProvider; +import org.eclipse.tm4e.ui.internal.widgets.ThemeContentProvider; +import org.eclipse.tm4e.ui.internal.widgets.ThemeLabelProvider; +import org.eclipse.tm4e.ui.themes.ITheme; +import org.eclipse.tm4e.ui.themes.IThemeAssociation; +import org.eclipse.tm4e.ui.themes.ThemeAssociation; + +/** + * Wizard page to create association between grammar and theme. + */ +final class CreateThemeAssociationWizardPage extends AbstractWizardPage { + + private static final String PAGE_NAME = CreateThemeAssociationWizardPage.class.getName(); + + @Nullable + private ComboViewer themeViewer; + + @Nullable + private ComboViewer grammarViewer; + + @Nullable + private final IGrammarDefinition initialDefinition; + + @Nullable + private final IThemeAssociation initialAssociation; + + @Nullable + private Button whenDarkButton; + + protected CreateThemeAssociationWizardPage(@Nullable final IGrammarDefinition initialDefinition, + @Nullable final IThemeAssociation initialAssociation) { + super(PAGE_NAME); + super.setTitle(TMUIMessages.CreateThemeAssociationWizardPage_title); + super.setDescription(TMUIMessages.CreateThemeAssociationWizardPage_description); + this.initialDefinition = initialDefinition; + this.initialAssociation = initialAssociation; + } + + @Override + protected void createBody(final Composite ancestor) { + final Composite parent = new Composite(ancestor, SWT.NONE); + parent.setFont(parent.getFont()); + parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + parent.setLayout(new GridLayout(4, false)); + + // TextMate theme + Label label = new Label(parent, SWT.NONE); + label.setText(TMUIMessages.CreateThemeAssociationWizardPage_theme_text); + final var themeViewer = this.themeViewer = new ComboViewer(parent); + themeViewer.setLabelProvider(new ThemeLabelProvider()); + themeViewer.setContentProvider(new ThemeContentProvider()); + themeViewer.setInput(TMUIPlugin.getThemeManager()); + themeViewer.getControl().setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + themeViewer.getControl().addListener(SWT.Selection, this); + + label = new Label(parent, SWT.NONE); + label.setText(TMUIMessages.CreateThemeAssociationWizardPage_grammar_text); + final var grammarViewer = this.grammarViewer = new ComboViewer(parent); + grammarViewer.setLabelProvider(new GrammarDefinitionLabelProvider()); + grammarViewer.setContentProvider(new GrammarDefinitionContentProvider()); + grammarViewer.setInput(TMEclipseRegistryPlugin.getGrammarRegistryManager()); + grammarViewer.getControl().setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + grammarViewer.getControl().addListener(SWT.Selection, this); + + if (initialDefinition != null) { + grammarViewer.setSelection(new StructuredSelection(initialDefinition)); + } + + final var whenDarkButton = this.whenDarkButton = new Button(parent, SWT.CHECK); + whenDarkButton.setText(TMUIMessages.CreateThemeAssociationWizardPage_whenDark_text); + final GridData data = new GridData(); + data.horizontalSpan = 4; + whenDarkButton.setLayoutData(data); + + final var initialAssociation = this.initialAssociation; + if (initialAssociation != null) { + final ITheme selectedTheme = TMUIPlugin.getThemeManager().getThemeById(initialAssociation.getThemeId()); + if (selectedTheme != null) { + themeViewer.setSelection(new StructuredSelection(selectedTheme)); + } + whenDarkButton.setSelection(initialAssociation.isWhenDark()); + } + } + + @Override + protected void initializeDefaultValues() { + setPageComplete(false); + } + + @Nullable + @Override + protected IStatus validatePage(final Event event) { + final var themeViewer = this.themeViewer; + if (themeViewer == null || themeViewer.getSelection().isEmpty()) { + return new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, + TMUIMessages.CreateThemeAssociationWizardPage_theme_error_required); + } + + final var grammarViewer = this.grammarViewer; + if (grammarViewer == null || grammarViewer.getSelection().isEmpty()) { + return new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, + TMUIMessages.CreateThemeAssociationWizardPage_grammar_error_required); + } + return null; + } + + IThemeAssociation getThemeAssociation() { + final String themeId = ((ITheme) castNonNull(themeViewer).getStructuredSelection().getFirstElement()).getId(); + final String scopeName = ((IGrammarDefinition) castNonNull(grammarViewer).getStructuredSelection() + .getFirstElement()).getScopeName(); + final boolean whenDark = castNonNull(whenDarkButton).getSelection(); + return new ThemeAssociation(themeId, scopeName, whenDark); + } + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/SelectGrammarWizardPage.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/SelectGrammarWizardPage.java index e9482bf50..ee66bb040 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/SelectGrammarWizardPage.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/SelectGrammarWizardPage.java @@ -1,156 +1,170 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.wizards; - -import java.io.File; -import java.io.FileInputStream; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.osgi.util.NLS; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.FileDialog; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; -import org.eclipse.tm4e.core.grammar.IGrammar; -import org.eclipse.tm4e.core.registry.Registry; -import org.eclipse.tm4e.registry.GrammarDefinition; -import org.eclipse.tm4e.registry.IGrammarDefinition; -import org.eclipse.tm4e.ui.TMUIPlugin; -import org.eclipse.tm4e.ui.internal.TMUIMessages; -import org.eclipse.tm4e.ui.internal.widgets.GrammarInfoWidget; - -/** - * Wizard page to select a textMate grammar file and register it in the grammar - * registry. - * - */ -public class SelectGrammarWizardPage extends AbstractWizardPage { - - private static final String PAGE_NAME = SelectGrammarWizardPage.class.getName(); - - protected static final String[] TEXTMATE_EXTENSIONS = new String[] {"*.tmLanguage","*.json"}; - - private Button browseFileSystemButton; - private Button browseWorkspaceButton; - - private Text grammarFileText; - - private GrammarInfoWidget grammarInfoWidget; - - // private ContentTypesBindingWidget contentTypesWidget; - - protected SelectGrammarWizardPage() { - super(PAGE_NAME); - super.setTitle(TMUIMessages.SelectGrammarWizardPage_title); - super.setDescription(TMUIMessages.SelectGrammarWizardPage_description); - } - - @Override - protected void createBody(Composite ancestor) { - Composite parent = new Composite(ancestor, SWT.NONE); - parent.setFont(parent.getFont()); - parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - parent.setLayout(new GridLayout(2, false)); - - // Text Field - grammarFileText = createText(parent, TMUIMessages.SelectGrammarWizardPage_file_label); - grammarFileText.addListener(SWT.Modify, this); - - // Buttons - Composite buttons = new Composite(parent, SWT.NONE); - buttons.setLayout(new GridLayout(2, false)); - GridData gd = new GridData(GridData.FILL_HORIZONTAL); - gd.horizontalSpan = 2; - gd.horizontalAlignment = SWT.RIGHT; - buttons.setLayoutData(gd); - - browseFileSystemButton = new Button(buttons, SWT.NONE); - browseFileSystemButton.setText(TMUIMessages.Button_browse_FileSystem); - browseFileSystemButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - FileDialog dialog = new FileDialog(parent.getShell()); - dialog.setFilterExtensions(TEXTMATE_EXTENSIONS); - dialog.setFilterPath(grammarFileText.getText()); - String result = dialog.open(); - if (result != null && result.length() > 0) { - grammarFileText.setText(result); - } - } - }); - - browseWorkspaceButton = new Button(buttons, SWT.NONE); - browseWorkspaceButton.setText(TMUIMessages.Button_browse_Workspace); - browseWorkspaceButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - // TODO - } - }); - - grammarInfoWidget = new GrammarInfoWidget(parent, SWT.NONE); - GridData data = new GridData(GridData.FILL_HORIZONTAL); - data.horizontalSpan = 2; - grammarInfoWidget.setLayoutData(data); - } - - private Text createText(Composite parent, String s) { - Label label = new Label(parent, SWT.NONE); - label.setText(s); - - Text text = new Text(parent, SWT.BORDER); - text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - return text; - } - - @Override - protected void initializeDefaultValues() { - setPageComplete(false); - } - - @Override - protected IStatus validatePage(Event event) { - grammarInfoWidget.refresh(null); - String path = grammarFileText.getText(); - if (path.length() == 0) { - return new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, - TMUIMessages.SelectGrammarWizardPage_file_error_required); - } - File f = new File(path); - Registry registry = new Registry(); - try { - IGrammar grammar = registry.loadGrammarFromPathSync(f.getName(), new FileInputStream(f)); - if (grammar == null || grammar.getScopeName() == null) { - return new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, - TMUIMessages.SelectGrammarWizardPage_file_error_invalid); - } - grammarInfoWidget.refresh(grammar); - } catch (Exception e) { - return new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, - NLS.bind(TMUIMessages.SelectGrammarWizardPage_file_error_load, e.getMessage()), e); - } - return null; - } - - public IGrammarDefinition getGrammarDefinition() { - return new GrammarDefinition(grammarInfoWidget.getScopeNameText().getText(), grammarFileText.getText()); - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.wizards; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import java.io.FileInputStream; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.tm4e.core.grammar.IGrammar; +import org.eclipse.tm4e.core.registry.Registry; +import org.eclipse.tm4e.registry.GrammarDefinition; +import org.eclipse.tm4e.registry.IGrammarDefinition; +import org.eclipse.tm4e.ui.TMUIPlugin; +import org.eclipse.tm4e.ui.internal.TMUIMessages; +import org.eclipse.tm4e.ui.internal.widgets.GrammarInfoWidget; + +/** + * Wizard page to select a textMate grammar file and register it in the grammar + * registry. + * + */ +final class SelectGrammarWizardPage extends AbstractWizardPage { + + private static final String PAGE_NAME = SelectGrammarWizardPage.class.getName(); + + private static final String[] TEXTMATE_EXTENSIONS = { + "*.tmLanguage", + "*.json", + "*.YAML-tmLanguage", + "*.yaml", + "*.yml" }; + + @Nullable + private Text grammarFileText; + + @Nullable + private GrammarInfoWidget grammarInfoWidget; + + // private ContentTypesBindingWidget contentTypesWidget; + + protected SelectGrammarWizardPage() { + super(PAGE_NAME); + super.setTitle(TMUIMessages.SelectGrammarWizardPage_title); + super.setDescription(TMUIMessages.SelectGrammarWizardPage_description); + } + + @Override + protected void createBody(final Composite ancestor) { + final Composite parent = new Composite(ancestor, SWT.NONE); + parent.setFont(parent.getFont()); + parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + parent.setLayout(new GridLayout(2, false)); + + // Text Field + final var grammarFileText = this.grammarFileText = createText(parent, + TMUIMessages.SelectGrammarWizardPage_file_label); + grammarFileText.addListener(SWT.Modify, this); + + // Buttons + final Composite buttons = new Composite(parent, SWT.NONE); + buttons.setLayout(new GridLayout(2, false)); + final GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 2; + gd.horizontalAlignment = SWT.RIGHT; + buttons.setLayoutData(gd); + + final var browseFileSystemButton = new Button(buttons, SWT.NONE); + browseFileSystemButton.setText(TMUIMessages.Button_browse_FileSystem); + browseFileSystemButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(@Nullable final SelectionEvent e) { + final var dialog = new FileDialog(parent.getShell()); + dialog.setFilterExtensions(TEXTMATE_EXTENSIONS); + dialog.setFilterPath(grammarFileText.getText()); + final String result = dialog.open(); + if (result != null && !result.isEmpty()) { + grammarFileText.setText(result); + } + } + }); + + final var browseWorkspaceButton = new Button(buttons, SWT.NONE); + browseWorkspaceButton.setText(TMUIMessages.Button_browse_Workspace); + browseWorkspaceButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(@Nullable final SelectionEvent e) { + // TODO + } + }); + + final GridData data = new GridData(GridData.FILL_HORIZONTAL); + data.horizontalSpan = 2; + grammarInfoWidget = new GrammarInfoWidget(parent, SWT.NONE); + grammarInfoWidget.setLayoutData(data); + } + + private Text createText(final Composite parent, final String s) { + final var label = new Label(parent, SWT.NONE); + label.setText(s); + + final var text = new Text(parent, SWT.BORDER); + text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + return text; + } + + @Override + protected void initializeDefaultValues() { + setPageComplete(false); + } + + @Nullable + @Override + protected IStatus validatePage(final Event event) { + final var grammarInfoWidget = this.grammarInfoWidget; + final var grammarFileText = this.grammarFileText; + if (grammarInfoWidget == null || grammarFileText == null) + return new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, + TMUIMessages.SelectGrammarWizardPage_file_error_required); + + grammarInfoWidget.refresh(null); + final String path = grammarFileText.getText(); + if (path.isEmpty()) { + return new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, + TMUIMessages.SelectGrammarWizardPage_file_error_required); + } + final var registry = new Registry(); + try (var is = new FileInputStream(path)) { + final IGrammar grammar = registry.loadGrammarFromPathSync(path, is); + if (grammar == null) { + return new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, + TMUIMessages.SelectGrammarWizardPage_file_error_invalid); + } + grammarInfoWidget.refresh(grammar); + } catch (final Exception e) { + return new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, + NLS.bind(TMUIMessages.SelectGrammarWizardPage_file_error_load, e.getMessage()), e); + } + return null; + } + + IGrammarDefinition getGrammarDefinition() { + return new GrammarDefinition( + castNonNull(grammarInfoWidget).getScopeNameText().getText(), + castNonNull(grammarFileText).getText()); + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/TextMateGrammarImportWizard.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/TextMateGrammarImportWizard.java index 77e20de04..4118d81bd 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/TextMateGrammarImportWizard.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/TextMateGrammarImportWizard.java @@ -1,86 +1,87 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.internal.wizards; - -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.wizard.Wizard; -import org.eclipse.tm4e.registry.IGrammarDefinition; -import org.eclipse.tm4e.registry.IGrammarRegistryManager; -import org.eclipse.tm4e.registry.TMEclipseRegistryPlugin; -import org.eclipse.ui.IImportWizard; -import org.eclipse.ui.IWorkbench; -import org.osgi.service.prefs.BackingStoreException; - -/** - * Wizard to import TextMate grammar. - * - */ -public class TextMateGrammarImportWizard extends Wizard implements IImportWizard { - - private SelectGrammarWizardPage mainPage; - - private IGrammarDefinition createdDefinition; - - private IGrammarRegistryManager grammarRegistryManager; - - private final boolean save; - - public TextMateGrammarImportWizard() { - this(true); - } - - public TextMateGrammarImportWizard(boolean save) { - this.save = save; - setGrammarRegistryManager(TMEclipseRegistryPlugin.getGrammarRegistryManager()); - } - - /** - * Set grammar registry to use to add the created grammar definitions. - * - * @param grammarRegistryManager - */ - public void setGrammarRegistryManager(IGrammarRegistryManager grammarRegistryManager) { - this.grammarRegistryManager = grammarRegistryManager; - } - - @Override - public void addPages() { - mainPage = new SelectGrammarWizardPage(); - addPage(mainPage); - } - - @Override - public boolean performFinish() { - IGrammarDefinition definition = mainPage.getGrammarDefinition(); - grammarRegistryManager.registerGrammarDefinition(definition); - if (save) { - try { - grammarRegistryManager.save(); - } catch (BackingStoreException e) { - e.printStackTrace(); - return false; - } - } - createdDefinition = definition; - return true; - } - - @Override - public void init(IWorkbench workbench, IStructuredSelection selection) { - - } - - public IGrammarDefinition getCreatedDefinition() { - return createdDefinition; - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.internal.wizards; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.tm4e.registry.IGrammarDefinition; +import org.eclipse.tm4e.registry.IGrammarRegistryManager; +import org.eclipse.tm4e.registry.TMEclipseRegistryPlugin; +import org.eclipse.ui.IImportWizard; +import org.eclipse.ui.IWorkbench; +import org.osgi.service.prefs.BackingStoreException; + +/** + * Wizard to import TextMate grammar. + * + */ +public final class TextMateGrammarImportWizard extends Wizard implements IImportWizard { + + @Nullable + private SelectGrammarWizardPage mainPage; + + @Nullable + private IGrammarDefinition createdDefinition; + + private IGrammarRegistryManager grammarRegistryManager = TMEclipseRegistryPlugin.getGrammarRegistryManager(); + + private final boolean save; + + public TextMateGrammarImportWizard(final boolean save) { + this.save = save; + } + + /** + * Set grammar registry to use to add the created grammar definitions. + * + * @param grammarRegistryManager + */ + public void setGrammarRegistryManager(final IGrammarRegistryManager grammarRegistryManager) { + this.grammarRegistryManager = grammarRegistryManager; + } + + @Override + public void addPages() { + mainPage = new SelectGrammarWizardPage(); + addPage(mainPage); + } + + @Override + public boolean performFinish() { + final IGrammarDefinition definition = castNonNull(mainPage).getGrammarDefinition(); + grammarRegistryManager.registerGrammarDefinition(definition); + if (save) { + try { + grammarRegistryManager.save(); + } catch (final BackingStoreException e) { + e.printStackTrace(); + return false; + } + } + createdDefinition = definition; + return true; + } + + @Override + public void init(@Nullable final IWorkbench workbench, @Nullable final IStructuredSelection selection) { + + } + + @Nullable + public IGrammarDefinition getCreatedDefinition() { + return createdDefinition; + } + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/package-info.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/package-info.java new file mode 100644 index 000000000..3e4ce4c34 --- /dev/null +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/internal/wizards/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.ui.internal.wizards; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/model/ITMModelManager.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/model/ITMModelManager.java index e6d8cf304..7cd48fd86 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/model/ITMModelManager.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/model/ITMModelManager.java @@ -1,37 +1,37 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.model; - -import org.eclipse.jface.text.IDocument; -import org.eclipse.tm4e.core.model.ITMModel; - -/** - * TextMate model manager API. - * - */ -public interface ITMModelManager { - - /** - * Connect the given document to a TextMate model. - * - * @param document - * @return the TextMate model connected to the document. - */ - ITMModel connect(IDocument document); - - /** - * Disconnect the TextMate model of the given document. - * - * @param document - */ - void disconnect(IDocument document); -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.model; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.tm4e.core.model.ITMModel; + +/** + * TextMate model manager API. + * + */ +public interface ITMModelManager { + + /** + * Connect the given document to a TextMate model. + * + * @param document + * @return the TextMate model connected to the document. + */ + ITMModel connect(IDocument document); + + /** + * Disconnect the TextMate model of the given document. + * + * @param document + */ + void disconnect(IDocument document); +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/model/package-info.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/model/package-info.java new file mode 100644 index 000000000..ab6797c27 --- /dev/null +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/model/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.ui.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/package-info.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/package-info.java new file mode 100644 index 000000000..2a2faeef4 --- /dev/null +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.ui; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/snippets/ISnippet.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/snippets/ISnippet.java index ff3d82467..74f7fcba7 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/snippets/ISnippet.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/snippets/ISnippet.java @@ -1,43 +1,43 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.snippets; - -import org.eclipse.tm4e.registry.ITMResource; - -/** - * - * Snippet API. - * - */ -public interface ISnippet extends ITMResource { - - /** - * Returns the name of the snippet. - * - * @return the name of the snippet. - */ - String getName(); - - /** - * Returns the scope name of the snippet. - * - * @return the scope name of the snippet. - */ - String getScopeName(); - - /** - * Returns the content of the snippet. - * - * @return the content of the snippet. - */ - String getContent(); -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.snippets; + +import org.eclipse.tm4e.registry.ITMResource; + +/** + * + * Snippet API. + * + */ +public interface ISnippet extends ITMResource { + + /** + * Returns the name of the snippet. + * + * @return the name of the snippet. + */ + String getName(); + + /** + * Returns the scope name of the snippet. + * + * @return the scope name of the snippet. + */ + String getScopeName(); + + /** + * Returns the content of the snippet. + * + * @return the content of the snippet. + */ + String getContent(); +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/snippets/ISnippetManager.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/snippets/ISnippetManager.java index 8c0712bb9..00b331e22 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/snippets/ISnippetManager.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/snippets/ISnippetManager.java @@ -1,27 +1,27 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.snippets; - -/** - * Snippet manager API. - * - */ -public interface ISnippetManager { - - /** - * Returns list of snippet for a given scope name and empty otherwise. - * - * @param scopeName - * @return list of snippet for a given scope name and empty otherwise. - */ - ISnippet[] getSnippets(String scopeName); -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.snippets; + +/** + * Snippet manager API. + * + */ +public interface ISnippetManager { + + /** + * Returns list of snippet for a given scope name and empty otherwise. + * + * @param scopeName + * @return list of snippet for a given scope name and empty otherwise. + */ + ISnippet[] getSnippets(String scopeName); +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/snippets/package-info.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/snippets/package-info.java new file mode 100644 index 000000000..627bca121 --- /dev/null +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/snippets/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.ui.snippets; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/text/ITMPresentationReconcilerListener.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/text/ITMPresentationReconcilerListener.java index 29b976c8c..fd1eab970 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/text/ITMPresentationReconcilerListener.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/text/ITMPresentationReconcilerListener.java @@ -1,46 +1,47 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.text; - -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.ITextViewer; -import org.eclipse.jface.text.TextPresentation; - -/** - * TextMate presentation reconciler listener. - * - */ -public interface ITMPresentationReconcilerListener { - - /** - * Install the given viewer and document. - * - * @param viewer - * @param document - */ - void install(ITextViewer viewer, IDocument document); - - /** - * Uninstall. - */ - void uninstall(); - - /** - * Colorize the StyledText with the given text presentation. - * - * @param presentation - * the text presentation. - * @param error - * when there are error. - */ - void colorize(TextPresentation presentation, Throwable error); -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.text; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.TextPresentation; + +/** + * TextMate presentation reconciler listener. + * + */ +public interface ITMPresentationReconcilerListener { + + /** + * Install the given viewer and document. + * + * @param viewer + * @param document + */ + void install(ITextViewer viewer, IDocument document); + + /** + * Uninstall. + */ + void uninstall(); + + /** + * Colorize the StyledText with the given text presentation. + * + * @param presentation + * the text presentation. + * @param error + * when there are error. + */ + void colorize(TextPresentation presentation, @Nullable Throwable error); +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/text/TMPresentationReconciler.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/text/TMPresentationReconciler.java index e9168969d..b6da491f0 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/text/TMPresentationReconciler.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/text/TMPresentationReconciler.java @@ -1,856 +1,901 @@ -/** - * Copyright (c) 2015-2019 Angelo ZERR. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - * Pierre-Yves B. - Issue #220 Switch to theme only works once for open editor - * IBM Corporation Gerald Mitchell - bug fix - */ -package org.eclipse.tm4e.ui.text; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -import org.eclipse.core.runtime.Assert; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Path; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; -import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.CursorLinePainter; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IPainter; -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.ITextInputListener; -import org.eclipse.jface.text.ITextListener; -import org.eclipse.jface.text.ITextOperationTarget; -import org.eclipse.jface.text.ITextViewer; -import org.eclipse.jface.text.ITextViewerExtension5; -import org.eclipse.jface.text.PaintManager; -import org.eclipse.jface.text.Region; -import org.eclipse.jface.text.TextAttribute; -import org.eclipse.jface.text.TextEvent; -import org.eclipse.jface.text.TextPresentation; -import org.eclipse.jface.text.TextViewer; -import org.eclipse.jface.text.presentation.IPresentationDamager; -import org.eclipse.jface.text.presentation.IPresentationReconciler; -import org.eclipse.jface.text.presentation.IPresentationRepairer; -import org.eclipse.jface.text.rules.IToken; -import org.eclipse.jface.text.rules.Token; -import org.eclipse.jface.text.source.SourceViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.StyleRange; -import org.eclipse.swt.custom.StyledText; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.widgets.Control; -import org.eclipse.tm4e.core.TMException; -import org.eclipse.tm4e.core.grammar.IGrammar; -import org.eclipse.tm4e.core.model.IModelTokensChangedListener; -import org.eclipse.tm4e.core.model.ITMModel; -import org.eclipse.tm4e.core.model.ModelTokensChangedEvent; -import org.eclipse.tm4e.core.model.Range; -import org.eclipse.tm4e.core.model.TMToken; -import org.eclipse.tm4e.registry.TMEclipseRegistryPlugin; -import org.eclipse.tm4e.ui.TMUIPlugin; -import org.eclipse.tm4e.ui.internal.model.TMDocumentModel; -import org.eclipse.tm4e.ui.internal.preferences.PreferenceConstants; -import org.eclipse.tm4e.ui.internal.text.TMPresentationReconcilerTestGenerator; -import org.eclipse.tm4e.ui.internal.themes.ThemeManager; -import org.eclipse.tm4e.ui.model.ITMModelManager; -import org.eclipse.tm4e.ui.themes.ITheme; -import org.eclipse.tm4e.ui.themes.IThemeManager; -import org.eclipse.tm4e.ui.themes.ITokenProvider; -import org.eclipse.tm4e.ui.utils.ClassHelper; -import org.eclipse.tm4e.ui.utils.ContentTypeHelper; -import org.eclipse.tm4e.ui.utils.ContentTypeInfo; -import org.eclipse.tm4e.ui.utils.PreferenceUtils; -import org.eclipse.ui.IEditorPart; - -/** - * TextMate presentation reconciler which must be initialized with: - * - *
      - *
    • a TextMate grammar {@link IGrammar} used to initialize the TextMate model - * {@link ITMDocumentModel}.
    • - *
    • a token provider {@link ITokenProvider} to retrieve the {@link IToken} - * from a TextMate token type .
    • - *
    - * - */ -public class TMPresentationReconciler implements IPresentationReconciler { - - /** - * The default text attribute if non is returned as data by the current token - */ - private final Token defaultToken; - - /** The target viewer. */ - private ITextViewer viewer; - /** The internal listener. */ - private final InternalListener internalListener; - - private IGrammar grammar; - private boolean forcedGrammar; - - private ITokenProvider tokenProvider; - - private final TextAttribute fDefaultTextAttribute; - - private IPreferenceChangeListener themeChangeListener; - - private List listeners; - - private boolean initializeViewerColors; - - private boolean updateTextDecorations; - - /** - * true if the presentation reconciler is enabled (grammar and theme are - * available) and false otherwise. - */ - private boolean enabled; - - /** - * true if a {@link TMException} should be thrown if grammar or theme cannot be - * found and false otherwise. - */ - private boolean throwError; - - public TMPresentationReconciler() { - this.defaultToken = new Token(null); - this.internalListener = new InternalListener(); - this.fDefaultTextAttribute = new TextAttribute(null); - listeners = null; - if (TMEclipseRegistryPlugin.isDebugOptionEnabled("org.eclipse.tm4e.ui/debug/log/GenerateTest")) { - addTMPresentationReconcilerListener(new TMPresentationReconcilerTestGenerator()); - } - setThrowError(TMEclipseRegistryPlugin.isDebugOptionEnabled("org.eclipse.tm4e.ui/debug/log/ThrowError")); - } - - /** - * Listener to recolorize editors when E4 Theme from General / Appearance - * preferences changed or TextMate theme changed.. - * - */ - private class ThemeChangeListener implements IPreferenceChangeListener { - - @Override - public void preferenceChange(PreferenceChangeEvent event) { - IThemeManager themeManager = TMUIPlugin.getThemeManager(); - if (PreferenceConstants.E4_THEME_ID.equals(event.getKey())) { - preferenceThemeChange((String) event.getNewValue(), themeManager); - } else if (PreferenceConstants.THEME_ASSOCIATIONS.equals(event.getKey())) { - preferenceThemeChange(PreferenceUtils.getE4PreferenceCSSThemeId(), themeManager); - } - } - - private void preferenceThemeChange(String eclipseThemeId, IThemeManager themeManager) { - IDocument document = viewer.getDocument(); - if (document == null) { - return; - } - if (grammar == null) { - return; - } - // Select the well TextMate theme from the given E4 theme id. - boolean dark = themeManager.isDarkEclipseTheme(eclipseThemeId); - ITokenProvider newTheme = themeManager.getThemeForScope(grammar.getScopeName(), dark); - setTheme(newTheme); - } - } - - /** - * Internal listener class. - */ - class InternalListener implements ITextInputListener, IModelTokensChangedListener, ITextListener { - - private void fireInstall(ITextViewer viewer, IDocument document) { - if (listeners == null) { - return; - } - synchronized (listeners) { - for (ITMPresentationReconcilerListener listener : listeners) { - listener.install(viewer, document); - } - } - } - - private void fireUninstall() { - if (listeners == null) { - return; - } - synchronized (listeners) { - for (ITMPresentationReconcilerListener listener : listeners) { - listener.uninstall(); - } - } - } - - @Override - public void inputDocumentAboutToBeChanged(IDocument oldDocument, IDocument newDocument) { - if (oldDocument != null) { - viewer.removeTextListener(this); - getTMModelManager().disconnect(oldDocument); - fireUninstall(); - } - } - - @Override - public void inputDocumentChanged(IDocument oldDocument, IDocument newDocument) { - if (newDocument == null) { - return; - } - fireInstall(viewer, newDocument); - try { - viewer.addTextListener(this); - // Update the grammar - IGrammar localGrammar = findGrammar(newDocument); - - if (localGrammar != null) { - TMPresentationReconciler.this.grammar = localGrammar; - } else if (isThrowError()) { - throw new TMException("Cannot find TextMate grammar for the given document"); - } - - // Update the theme - if (localGrammar != null) { - String scopeName = localGrammar.getScopeName(); - if (tokenProvider == null) { - tokenProvider = TMUIPlugin.getThemeManager().getThemeForScope(scopeName, viewer.getTextWidget().getBackground().getRGB()); - } - if (tokenProvider != null) { - applyThemeEditor(); - } else if (isThrowError()) { - throw new TMException("Cannot find Theme for the given grammar '" + scopeName + "'"); - } - } - - boolean enable = TMPresentationReconciler.this.enabled = localGrammar != null && tokenProvider != null; - if (enable) { - // Connect a TextModel to the new document. - ITMModel model = getTMModelManager().connect(newDocument); - model.setGrammar(localGrammar); - - // Add model listener - model.addModelTokensChangedListener(this); - } - } catch (CoreException e) { - Platform.getLog(Platform.getBundle(TMEclipseRegistryPlugin.PLUGIN_ID)).log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, "Error while initializing TextMate model.", e)); - } - } - - /** - * Finds a grammar for the given document. - * @param newDocument - * @return - * @throws CoreException - */ - protected IGrammar findGrammar(@NonNull IDocument newDocument) throws CoreException { - IGrammar localGrammar = forcedGrammar ? TMPresentationReconciler.this.grammar : null; - if (localGrammar != null) { - return localGrammar; - } - ContentTypeInfo info = ContentTypeHelper.findContentTypes(newDocument); - if (info == null) { - return null; - } - return findGrammar(info); - } - - @Override - public void textChanged(TextEvent e) { - if (!e.getViewerRedrawState()) { - return; - } - // changed text: propagate previous style, which will be overridden - // later asynchronously by TM - if (e.getDocumentEvent() != null) { - int diff = e.getText().length() - e.getLength(); - if (diff == 0 || e.getOffset() <= 0) { - return; - } - StyleRange range = viewer.getTextWidget().getStyleRangeAtOffset(e.getOffset() - 1); - if (range == null) { - return; - } - range.length = Math.max(0, range.length + diff); - viewer.getTextWidget().setStyleRange(range); - return; - } - - // TextViewer#invalidateTextPresentation is called (because - // of validation, folding, etc) - // case 2), do the colorization. - IDocument document = viewer.getDocument(); - if (document == null) { - return; - } - IRegion region = computeRegionToRedraw(e, document); - if (enabled) { - // case where there is grammar & theme -> update text presentation with the - // grammar tokens - ITMModel model = getTMModelManager().connect(document); - if (model == null) { - return; - } - try { - TMPresentationReconciler.this.colorize(region, (TMDocumentModel) model); - } catch (BadLocationException e1) { - TMUIPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e1.getMessage(), e1)); - } - } else { - // case where there is no grammar & theme -> update text presentation with the - // default styles (ex: to support highlighting with GenericEditor) - TextPresentation presentation = new TextPresentation(region, 100); - presentation.setDefaultStyleRange( - new StyleRange(region.getOffset(), region.getLength(), null, null)); - applyTextRegionCollection(presentation); - } - } - - protected @NonNull IRegion computeRegionToRedraw(@NonNull TextEvent e, @NonNull IDocument document) { - IRegion region = null; - if (e.getOffset() == 0 && e.getLength() == 0 && e.getText() == null) { - // redraw state change, damage the whole document - region = new Region(0, document.getLength()); - } else { - region = widgetRegion2ModelRegion(e); - } - if (region == null || region.getLength() == 0) { - return new Region(0, 0); - } - return region; - } - - /** - * Translates the given text event into the corresponding range of the viewer's - * document. - * - * @param e - * the text event - * @return the widget region corresponding the region of the given event or - * null if none - * @since 2.1 - */ - private IRegion widgetRegion2ModelRegion(TextEvent e) { - String text = e.getText(); - int length = text == null ? 0 : text.length(); - if (viewer instanceof ITextViewerExtension5) { - ITextViewerExtension5 extension = (ITextViewerExtension5) viewer; - return extension.widgetRange2ModelRange(new Region(e.getOffset(), length)); - } - IRegion visible = viewer.getVisibleRegion(); - return new Region(e.getOffset() + visible.getOffset(), length); - } - - @Override - public void modelTokensChanged(ModelTokensChangedEvent event) { - Control control = viewer.getTextWidget(); - if (control != null) { - control.getDisplay().asyncExec(() -> { - if (viewer != null) { - colorize(event); - } - }); - } - } - - private void colorize(ModelTokensChangedEvent event) { - IDocument document = viewer.getDocument(); - if (document == null) { - return; - } - ITMModel model = event.model; - if (! (model instanceof TMDocumentModel)) { - return; - } - TMDocumentModel docModel = (TMDocumentModel) model; - for (Range range : event.ranges) { - try { - int length = document.getLineOffset(range.toLineNumber - 1) + document.getLineLength(range.toLineNumber - 1) - document.getLineOffset(range.fromLineNumber - 1); - IRegion region = new Region(document.getLineOffset(range.fromLineNumber -1), length); - TMPresentationReconciler.this.colorize(region, docModel); - } catch (BadLocationException ex) { - TMUIPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, ex.getMessage(), ex)); - } - } - } - - private IGrammar findGrammar(ContentTypeInfo info) { - if (info == null) { - return null; - } - IContentType[] contentTypes = info.getContentTypes(); - // Discover the well grammar from the contentTypes - IGrammar res = TMEclipseRegistryPlugin.getGrammarRegistryManager().getGrammarFor(contentTypes); - if (res == null) { - // Discover the well grammar from the filetype - String fileName = info.getFileName(); - if (fileName != null) { - String fileType = new Path(fileName).getFileExtension(); - res = TMEclipseRegistryPlugin.getGrammarRegistryManager().getGrammarForFileType(fileType); - } - } - return res; - } - } - - public void setGrammar(IGrammar grammar) { - boolean changed = (viewer != null && ((this.grammar == null) || !this.grammar.equals(grammar))); - this.grammar = grammar; - this.forcedGrammar = true; - if (changed) { - // Grammar has changed, recreate the TextMate model - IDocument document = viewer.getDocument(); - if (document == null) { - return; - } - internalListener.inputDocumentAboutToBeChanged(viewer.getDocument(), null); - internalListener.inputDocumentChanged(null, document); - } - } - - public IGrammar getGrammar() { - return grammar; - } - - public ITokenProvider getTokenProvider() { - return tokenProvider; - } - - public void setTheme(final ITokenProvider newTheme) { - final ITokenProvider oldTheme = this.tokenProvider; - if (!Objects.equals(oldTheme, newTheme) && grammar != null) { - this.tokenProvider = newTheme; - applyThemeEditor(); - IDocument document = viewer.getDocument(); - ITMModel model = getTMModelManager().connect(document); - if (! (model instanceof TMDocumentModel)) { - return; - } - TMDocumentModel docModel = (TMDocumentModel) model; - try { - colorize(new Region(0, document.getLength()), docModel); - } catch (BadLocationException e) { - TMUIPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); - } - } - } - - @Override - public void install(ITextViewer viewer) { - Assert.isNotNull(viewer); - - this.viewer = viewer; - viewer.addTextInputListener(internalListener); - - IDocument document = viewer.getDocument(); - if (document != null) { - internalListener.inputDocumentChanged(null, document); - } - themeChangeListener = new ThemeChangeListener(); - ThemeManager.getInstance().addPreferenceChangeListener(themeChangeListener); - } - - @Override - public void uninstall() { - viewer.removeTextInputListener(internalListener); - // Ensure we uninstall all listeners - internalListener.inputDocumentAboutToBeChanged(viewer.getDocument(), null); - if (themeChangeListener != null) { - ThemeManager.getInstance().removePreferenceChangeListener(themeChangeListener); - } - themeChangeListener = null; - } - - @Override - public IPresentationDamager getDamager(String contentType) { - return null; - } - - @Override - public IPresentationRepairer getRepairer(String contentType) { - return null; - } - - private ITMModelManager getTMModelManager() { - return TMUIPlugin.getTMModelManager(); - } - - void colorize(@NonNull IRegion damage, @NonNull TMDocumentModel model) throws BadLocationException{ - IDocument document = model.getDocument(); - final int fromLineNumber = document.getLineOfOffset(damage.getOffset()); - final int toLineNumber = document.getLineOfOffset(damage.getOffset() + damage.getLength()); - applyThemeEditorIfNeeded(); - // Refresh the UI Presentation - TMUIPlugin.getDefault().trace("Render from: " + fromLineNumber + " to: " + toLineNumber); - TextPresentation presentation = null; - Throwable error = null; - try { - presentation = new TextPresentation(damage, 1000); - - int lastStart = presentation.getExtent().getOffset(); - int length = 0; - boolean firstToken = true; - IToken lastToken = Token.UNDEFINED; - TextAttribute lastAttribute = getTokenTextAttribute(lastToken); - - List tokens = null; - for (int line = fromLineNumber; line <= toLineNumber; line++) { - tokens = model.getLineTokens(line); - if (tokens == null) { - // TextMate tokens was not computed for this line. - // This case comes from when the viewer is invalidated (by - // validation for instance) and textChanged is called. - // see https://github.com/eclipse/tm4e/issues/78 - TMUIPlugin.getDefault().trace("TextMate tokens not available for line " + line); - break; - } - int startLineOffset = document.getLineOffset(line); - for (int i = 0; i < tokens.size(); i++) { - TMToken currentToken = tokens.get(i); - TMToken nextToken = (i + 1 < tokens.size()) ? tokens.get(i + 1) : null; - int tokenStartIndex = currentToken.startIndex; - - if (isBeforeRegion(currentToken, startLineOffset, damage)) { - // The token is before the damage region - if (nextToken != null) { - if (isBeforeRegion(nextToken, startLineOffset, damage)) { - // ignore it - continue; - } else { - tokenStartIndex = damage.getOffset() - startLineOffset; - } - } else { - tokenStartIndex = damage.getOffset() - startLineOffset; - IToken token = toToken(currentToken); - lastAttribute = getTokenTextAttribute(token); - length += getTokenLengh(tokenStartIndex, nextToken, line, document); - firstToken = false; - // ignore it - continue; - } - } else if (isAfterRegion(currentToken, startLineOffset, damage)) { - // The token is after the damage region, stop the - // colorization process - break; - } - - IToken token = toToken(currentToken); - TextAttribute attribute = getTokenTextAttribute(token); - if (lastAttribute != null && lastAttribute.equals(attribute)) { - length += getTokenLengh(tokenStartIndex, nextToken, line, document); - firstToken = false; - } else { - if (!firstToken) { - addRange(presentation, lastStart, length, lastAttribute); - } - firstToken = false; - lastToken = token; - lastAttribute = attribute; - lastStart = tokenStartIndex + startLineOffset; - length = getTokenLengh(tokenStartIndex, nextToken, line, document); - } - } - } - // adjust the length - length = Math.min(length, damage.getOffset() + damage.getLength() - lastStart); - addRange(presentation, lastStart, length, lastAttribute); - applyTextRegionCollection(presentation); - } catch (Exception e) { - TMUIPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); - } finally { - fireColorize(presentation, error); - } - } - - /** - * Return true if the given token is before the given region and false - * otherwise. - * - * @param token - * @param startLineOffset - * @param damage - * @return - */ - private boolean isBeforeRegion(TMToken token, int startLineOffset, IRegion damage) { - return token.startIndex + startLineOffset < damage.getOffset(); - } - - /** - * Return true if the given token is after the given region and false otherwise. - * - * @param t - * @param startLineOffset - * @param damage - * @return - */ - private boolean isAfterRegion(TMToken t, int startLineOffset, IRegion damage) { - return t.startIndex + startLineOffset >= damage.getOffset() + damage.getLength(); - } - - private IToken toToken(TMToken t) { - IToken token = getTokenProvider().getToken(t.type); - if (token != null) { - return token; - } - return defaultToken; - } - - private int getTokenLengh(int tokenStartIndex, TMToken nextToken, int line, IDocument document) - throws BadLocationException { - if (nextToken != null) { - return nextToken.startIndex - tokenStartIndex; - } - return document.getLineLength(line) - tokenStartIndex; - } - - /** - * Returns a text attribute encoded in the given token. If the token's data is - * not null and a text attribute it is assumed that it is the - * encoded text attribute. It returns the default text attribute if there is no - * encoded text attribute found. - * - * @param token - * the token whose text attribute is to be determined - * @return the token's text attribute - */ - protected TextAttribute getTokenTextAttribute(IToken token) { - Object data = token.getData(); - if (data instanceof TextAttribute) { - return (TextAttribute) data; - } - return fDefaultTextAttribute; - } - - /** - * Adds style information to the given text presentation. - * - * @param presentation - * the text presentation to be extended - * @param offset - * the offset of the range to be styled - * @param length - * the length of the range to be styled - * @param attr - * the attribute describing the style of the range to be styled - * @param lastLineStyleRanges - */ - protected void addRange(TextPresentation presentation, int offset, int length, TextAttribute attr) { - if (attr != null) { - int style = attr.getStyle(); - int fontStyle = style & (SWT.ITALIC | SWT.BOLD | SWT.NORMAL); - StyleRange styleRange = new StyleRange(offset, length, attr.getForeground(), attr.getBackground(), - fontStyle); - styleRange.strikeout = (style & TextAttribute.STRIKETHROUGH) != 0; - styleRange.underline = (style & TextAttribute.UNDERLINE) != 0; - styleRange.font = attr.getFont(); - presentation.addStyleRange(styleRange); - } - } - - /** - * Applies the given text presentation to the text viewer the presentation - * reconciler is installed on. - * - * @param presentation - * the text presentation to be applied to the text viewer - */ - private void applyTextRegionCollection(TextPresentation presentation) { - viewer.changeTextPresentation(presentation, false); - } - - /** - * Add a TextMate presentation reconciler listener. - * - * @param listener - * the TextMate presentation reconciler listener to add. - */ - public void addTMPresentationReconcilerListener(ITMPresentationReconcilerListener listener) { - if (listeners == null) { - listeners = new ArrayList<>(); - } - synchronized (listeners) { - if (!listeners.contains(listener)) { - listeners.add(listener); - } - } - } - - /** - * Remove a TextMate presentation reconciler listener. - * - * @param listener - * the TextMate presentation reconciler listener to remove. - */ - public void removeTMPresentationReconcilerListener(ITMPresentationReconcilerListener listener) { - if (listeners == null) { - return; - } - synchronized (listeners) { - listeners.remove(listener); - } - } - - /** - * Fire colorize. - * - * @param presentation - * @param error - */ - private void fireColorize(TextPresentation presentation, Throwable error) { - if (listeners == null) { - return; - } - synchronized (listeners) { - for (ITMPresentationReconcilerListener listener : listeners) { - listener.colorize(presentation, error); - } - } - } - - public static TMPresentationReconciler getTMPresentationReconciler(IEditorPart editorPart) { - if (editorPart == null) { - return null; - } - @Nullable ITextOperationTarget target = editorPart.getAdapter(ITextOperationTarget.class); - if (target instanceof ITextViewer) { - ITextViewer textViewer = ((ITextViewer) target); - return TMPresentationReconciler.getTMPresentationReconciler(textViewer); - } - return null; - } - - /** - * Returns the {@link TMPresentationReconciler} of the given text viewer and - * null otherwise. - * - * @param textViewer - * @return the {@link TMPresentationReconciler} of the given text viewer and - * null otherwise. - */ - public static TMPresentationReconciler getTMPresentationReconciler(ITextViewer textViewer) { - try { - Field field = SourceViewer.class.getDeclaredField("fPresentationReconciler"); - if (field != null) { - field.setAccessible(true); - Object presentationReconciler = field.get(textViewer); - //field is IPresentationRecounciler, looking for TMPresentationReconciler implementation - return presentationReconciler instanceof TMPresentationReconciler - ? (TMPresentationReconciler) presentationReconciler - : null; - } - } catch (SecurityException | NoSuchFieldException e) { - // if SourceViewer class no longer has fPresentationReconciler or changes access level - TMUIPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); - } catch (IllegalArgumentException | IllegalAccessException | NullPointerException | ExceptionInInitializerError iae) { - //This should not be logged as an error. This is an expected possible outcome of field.get(textViewer). - //The method assumes ITextViewer is actually ISourceViewer, and specifically the SourceViewer implementation - // that was available at the current build. This code also works with any implementation that follows the - // internal structure if also an ITextViewer. - //If these assumptions are false, the method should return null. Logging causes repeat noise. - } - return null; - } - - /** - * Initialize foreground, background color, current line highlight from the - * current theme. - * - */ - private void applyThemeEditor() { - this.initializeViewerColors = false; - this.updateTextDecorations = false; - applyThemeEditorIfNeeded(); - } - - /** - * Initialize foreground, background color, current line highlight from the - * current theme if needed. - * - */ - private void applyThemeEditorIfNeeded() { - if (!initializeViewerColors) { - StyledText styledText = viewer.getTextWidget(); - ((ITheme) tokenProvider).initializeViewerColors(styledText); - initializeViewerColors = true; - } - if (updateTextDecorations) { - return; - } - try { - // Ugly code to update "current line highlight" : - // - get the PaintManager from the ITextViewer with reflection. - // - get the list of IPainter of PaintManager with reflection - // - loop for IPainter to retrieve CursorLinePainter which manages "current line - // highlight". - PaintManager paintManager = ClassHelper.getFieldValue(viewer, "fPaintManager", TextViewer.class); - if (paintManager == null) { - return; - } - List painters = ClassHelper.getFieldValue(paintManager, "fPainters", PaintManager.class); - if (painters == null) { - return; - } - for (IPainter painter : painters) { - if (painter instanceof CursorLinePainter) { - // Update current line highlight - Color background = tokenProvider.getEditorCurrentLineHighlight(); - if (background != null) { - ((CursorLinePainter) painter).setHighlightColor(background); - } - updateTextDecorations = true; - } - } - } catch (Exception e) { - TMUIPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); - } - } - - /** - * Set true if a {@link TMException} should be thrown if grammar or theme cannot - * be found and false otherwise. - * - * @param throwError - */ - public void setThrowError(boolean throwError) { - this.throwError = throwError; - } - - /** - * Return true if a {@link TMException} should be thrown if grammar or theme - * cannot be found and false otherwise. - * - * @return true if a {@link TMException} should be thrown if grammar or theme - * cannot be found and false otherwise. - */ - public boolean isThrowError() { - return throwError; - } - - /** - * Returns true if the presentation reconciler is enabled (grammar and theme are - * available) and false otherwise. - * - * @return true if the presentation reconciler is enabled (grammar and theme are - * available) and false otherwise. - */ - - public boolean isEnabled() { - return enabled; - } - -} +/** + * Copyright (c) 2015-2022 Angelo ZERR. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + * Pierre-Yves B. - Issue #220 Switch to theme only works once for open editor + * IBM Corporation Gerald Mitchell - bug fix + */ +package org.eclipse.tm4e.ui.text; + +import static org.eclipse.tm4e.core.internal.utils.NullSafetyHelper.*; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; +import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.CursorLinePainter; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IPainter; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextInputListener; +import org.eclipse.jface.text.ITextListener; +import org.eclipse.jface.text.ITextOperationTarget; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.ITextViewerExtension5; +import org.eclipse.jface.text.PaintManager; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.TextEvent; +import org.eclipse.jface.text.TextPresentation; +import org.eclipse.jface.text.TextViewer; +import org.eclipse.jface.text.presentation.IPresentationDamager; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.presentation.IPresentationRepairer; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyleRange; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.widgets.Control; +import org.eclipse.tm4e.core.TMException; +import org.eclipse.tm4e.core.grammar.IGrammar; +import org.eclipse.tm4e.core.model.IModelTokensChangedListener; +import org.eclipse.tm4e.core.model.ITMModel; +import org.eclipse.tm4e.core.model.ModelTokensChangedEvent; +import org.eclipse.tm4e.core.model.Range; +import org.eclipse.tm4e.core.model.TMToken; +import org.eclipse.tm4e.registry.TMEclipseRegistryPlugin; +import org.eclipse.tm4e.ui.TMUIPlugin; +import org.eclipse.tm4e.ui.internal.model.TMDocumentModel; +import org.eclipse.tm4e.ui.internal.preferences.PreferenceConstants; +import org.eclipse.tm4e.ui.internal.text.TMPresentationReconcilerTestGenerator; +import org.eclipse.tm4e.ui.internal.themes.ThemeManager; +import org.eclipse.tm4e.ui.internal.utils.ClassHelper; +import org.eclipse.tm4e.ui.internal.utils.ContentTypeHelper; +import org.eclipse.tm4e.ui.internal.utils.ContentTypeInfo; +import org.eclipse.tm4e.ui.internal.utils.PreferenceUtils; +import org.eclipse.tm4e.ui.model.ITMModelManager; +import org.eclipse.tm4e.ui.themes.ITheme; +import org.eclipse.tm4e.ui.themes.IThemeManager; +import org.eclipse.tm4e.ui.themes.ITokenProvider; +import org.eclipse.ui.IEditorPart; + +/** + * TextMate presentation reconciler which must be initialized with: + * + *
      + *
    • a TextMate grammar {@link IGrammar} used to initialize the TextMate model {@link TMDocumentModel}.
    • + *
    • a token provider {@link ITokenProvider} to retrieve the {@link IToken} from a TextMate token type .
    • + *
    + */ +public class TMPresentationReconciler implements IPresentationReconciler { + + /** + * The default text attribute if non is returned as data by the current token + */ + private final Token defaultToken; + + /** The target viewer. */ + @Nullable + private ITextViewer viewer; + + /** The internal listener. */ + private final InternalListener internalListener; + + @Nullable + private IGrammar grammar; + private boolean forcedGrammar; + + @Nullable + private ITokenProvider tokenProvider; + + private final TextAttribute fDefaultTextAttribute; + + @Nullable + private IPreferenceChangeListener themeChangeListener; + + private final List listeners = new ArrayList<>(); + + private boolean initializeViewerColors; + + private boolean updateTextDecorations; + + /** + * true if the presentation reconciler is enabled (grammar and theme are available) and false otherwise. + */ + private boolean enabled; + + /** + * true if a {@link TMException} should be thrown if grammar or theme cannot be found and false otherwise. + */ + private boolean throwError; + + public TMPresentationReconciler() { + this.defaultToken = new Token(null); + this.internalListener = new InternalListener(); + this.fDefaultTextAttribute = new TextAttribute(null); + if (TMEclipseRegistryPlugin.isDebugOptionEnabled("org.eclipse.tm4e.ui/debug/log/GenerateTest")) { + addTMPresentationReconcilerListener(new TMPresentationReconcilerTestGenerator()); + } + setThrowError(TMEclipseRegistryPlugin.isDebugOptionEnabled("org.eclipse.tm4e.ui/debug/log/ThrowError")); + } + + /** + * Listener to recolorize editors when E4 Theme from General / Appearance + * preferences changed or TextMate theme changed.. + */ + private final class ThemeChangeListener implements IPreferenceChangeListener { + + @Override + public void preferenceChange(@Nullable final PreferenceChangeEvent event) { + if(event == null) + return; + final IThemeManager themeManager = TMUIPlugin.getThemeManager(); + switch (event.getKey()) { + case PreferenceConstants.E4_THEME_ID: + preferenceThemeChange((String) event.getNewValue(), themeManager); + break; + case PreferenceConstants.THEME_ASSOCIATIONS: + preferenceThemeChange(PreferenceUtils.getE4PreferenceCSSThemeId(), themeManager); + break; + } + } + + void preferenceThemeChange(@Nullable final String eclipseThemeId, final IThemeManager themeManager) { + final var viewer = TMPresentationReconciler.this.viewer; + if (viewer == null) { + return; + } + + final IDocument document = viewer.getDocument(); + if (document == null) { + return; + } + + final var grammar = TMPresentationReconciler.this.grammar; + if (grammar == null) { + return; + } + // Select the well TextMate theme from the given E4 theme id. + final boolean dark = themeManager.isDarkEclipseTheme(eclipseThemeId); + final ITokenProvider newTheme = themeManager.getThemeForScope(grammar.getScopeName(), dark); + setTheme(newTheme); + } + } + + /** + * Internal listener class. + */ + private final class InternalListener implements ITextInputListener, IModelTokensChangedListener, ITextListener { + + void fireInstall(final ITextViewer viewer, final IDocument document) { + synchronized (listeners) { + for (final ITMPresentationReconcilerListener listener : listeners) { + listener.install(viewer, document); + } + } + } + + void fireUninstall() { + synchronized (listeners) { + for (final ITMPresentationReconcilerListener listener : listeners) { + listener.uninstall(); + } + } + } + + @Override + public void inputDocumentAboutToBeChanged(@Nullable final IDocument oldDocument, + @Nullable final IDocument newDocument) { + if (oldDocument == null) + return; + + final var viewer = TMPresentationReconciler.this.viewer; + if (viewer != null) { + viewer.removeTextListener(this); + } + getTMModelManager().disconnect(oldDocument); + fireUninstall(); + } + + @Override + public void inputDocumentChanged(@Nullable final IDocument oldDocument, @Nullable final IDocument newDocument) { + if (newDocument == null) { + return; + } + + final var viewer = TMPresentationReconciler.this.viewer; + if (viewer == null) + return; + + fireInstall(viewer, newDocument); + try { + viewer.addTextListener(this); + // Update the grammar + final IGrammar localGrammar = findGrammar(newDocument); + + if (localGrammar != null) { + TMPresentationReconciler.this.grammar = localGrammar; + } else if (isThrowError()) { + throw new TMException("Cannot find TextMate grammar for the given document"); + } + + // Update the theme + if (localGrammar != null) { + final String scopeName = localGrammar.getScopeName(); + if (tokenProvider == null) { + tokenProvider = TMUIPlugin.getThemeManager().getThemeForScope(scopeName, + viewer.getTextWidget().getBackground().getRGB()); + } + if (tokenProvider != null) { + applyThemeEditor(); + } else if (isThrowError()) { + throw new TMException("Cannot find Theme for the given grammar '" + scopeName + "'"); + } + } + + if (localGrammar != null) { + final var enable = TMPresentationReconciler.this.enabled = tokenProvider != null; + if (enable) { + // Connect a TextModel to the new document. + final ITMModel model = getTMModelManager().connect(newDocument); + model.setGrammar(localGrammar); + + // Add model listener + model.addModelTokensChangedListener(this); + } + } else { + TMPresentationReconciler.this.enabled = false; + } + } catch (final CoreException e) { + Platform.getLog(Platform.getBundle(TMEclipseRegistryPlugin.PLUGIN_ID)).log( + new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, "Error while initializing TextMate model.", e)); + } + } + + /** + * Finds a grammar for the given document. + * + * @throws CoreException + */ + @Nullable + IGrammar findGrammar(final IDocument newDocument) throws CoreException { + final IGrammar localGrammar = forcedGrammar ? TMPresentationReconciler.this.grammar : null; + if (localGrammar != null) { + return localGrammar; + } + final ContentTypeInfo info = ContentTypeHelper.findContentTypes(newDocument); + if (info == null) { + return null; + } + return findGrammar(info); + } + + @Override + public void textChanged(final @Nullable TextEvent e) { + if (e == null || !e.getViewerRedrawState()) { + return; + } + + final var viewer = TMPresentationReconciler.this.viewer; + if (viewer == null) + return; + + // changed text: propagate previous style, which will be overridden later asynchronously by TM + if (e.getDocumentEvent() != null) { + final int diff = e.getText().length() - e.getLength(); + if (diff == 0 || e.getOffset() <= 0) { + return; + } + final StyleRange range = viewer.getTextWidget().getStyleRangeAtOffset(e.getOffset() - 1); + if (range == null) { + return; + } + range.length = Math.max(0, range.length + diff); + viewer.getTextWidget().setStyleRange(range); + return; + } + + // TextViewer#invalidateTextPresentation is called (because of validation, folding, etc) + // case 2), do the colorization. + final IDocument document = viewer.getDocument(); + if (document == null) { + return; + } + final IRegion region = computeRegionToRedraw(e, document); + if (enabled) { + // case where there is grammar & theme -> update text presentation with the grammar tokens + final ITMModel model = getTMModelManager().connect(document); + + // It's possible that there are two or more SourceViewers opened for the same document, + // so when one of them is closed the existing TMModel is also "closed" and its TokenizerThread + // is interrupted and terminated. + // In this case, in order to let the others Source Viewers to continue working a new + // TMModel object is to be created for the document, so it should be initialized + // with the existing grammar as well as new ModelTokenListener is to be added + final var grammar = TMPresentationReconciler.this.grammar; + if (grammar != null) { + model.setGrammar(grammar); + model.addModelTokensChangedListener(this); + } + + try { + TMPresentationReconciler.this.colorize(region, (TMDocumentModel) model); + } catch (final BadLocationException e1) { + TMUIPlugin.log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e1.getMessage(), e1)); + } + } else { + // case where there is no grammar & theme -> update text presentation with the + // default styles (ex: to support highlighting with GenericEditor) + final TextPresentation presentation = new TextPresentation(region, 100); + presentation.setDefaultStyleRange( + new StyleRange(region.getOffset(), region.getLength(), null, null)); + applyTextRegionCollection(presentation); + } + } + + IRegion computeRegionToRedraw(final TextEvent e, final IDocument document) { + IRegion region = null; + if (e.getOffset() == 0 && e.getLength() == 0 && e.getText() == null) { + // redraw state change, damage the whole document + region = new Region(0, document.getLength()); + } else { + region = widgetRegion2ModelRegion(e); + } + if (region == null || region.getLength() == 0) { + return new Region(0, 0); + } + return region; + } + + /** + * Translates the given text event into the corresponding range of the viewer's document. + * + * @param e + * the text event + * @return the widget region corresponding the region of the given event or null if none + * + * @since 2.1 + */ + @Nullable + IRegion widgetRegion2ModelRegion(final TextEvent e) { + final String text = e.getText(); + final int length = text == null ? 0 : text.length(); + final var viewer = castNonNull(TMPresentationReconciler.this.viewer); + if (viewer instanceof ITextViewerExtension5) { + final ITextViewerExtension5 extension = (ITextViewerExtension5) viewer; + return extension.widgetRange2ModelRange(new Region(e.getOffset(), length)); + } + final IRegion visible = viewer.getVisibleRegion(); + return new Region(e.getOffset() + visible.getOffset(), length); + } + + @Override + public void modelTokensChanged(final ModelTokensChangedEvent event) { + final var viewer = TMPresentationReconciler.this.viewer; + if (viewer != null) { + final Control control = viewer.getTextWidget(); + if (control != null) { + control.getDisplay().asyncExec(() -> { + colorize(event); + }); + } + } + } + + void colorize(final ModelTokensChangedEvent event) { + final var viewer = TMPresentationReconciler.this.viewer; + if (viewer == null) + return; + + final IDocument document = viewer.getDocument(); + if (document == null) { + return; + } + final ITMModel model = event.model; + if (!(model instanceof TMDocumentModel)) { + return; + } + final TMDocumentModel docModel = (TMDocumentModel) model; + for (final Range range : event.ranges) { + try { + final int length = document.getLineOffset(range.toLineNumber - 1) + + document.getLineLength(range.toLineNumber - 1) + - document.getLineOffset(range.fromLineNumber - 1); + final IRegion region = new Region(document.getLineOffset(range.fromLineNumber - 1), length); + TMPresentationReconciler.this.colorize(region, docModel); + } catch (final BadLocationException ex) { + TMUIPlugin.log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, ex.getMessage(), ex)); + } + } + } + + @Nullable + IGrammar findGrammar(@Nullable final ContentTypeInfo info) { + if (info == null) { + return null; + } + final IContentType[] contentTypes = info.getContentTypes(); + // Discover the well grammar from the contentTypes + IGrammar res = TMEclipseRegistryPlugin.getGrammarRegistryManager().getGrammarFor(contentTypes); + if (res == null) { + // Discover the well grammar from the filetype + final String fileName = info.getFileName(); + if (fileName.indexOf('.') > -1) { + final String fileType = new Path(fileName).getFileExtension(); + res = TMEclipseRegistryPlugin.getGrammarRegistryManager().getGrammarForFileType(fileType); + } + } + return res; + } + } + + public void setGrammar(@Nullable final IGrammar grammar) { + var viewer = this.viewer; + final boolean changed = (viewer != null && ((this.grammar == null) || !Objects.equals(grammar, this.grammar))); + this.grammar = grammar; + this.forcedGrammar = true; + if (changed) { + // Grammar has changed, recreate the TextMate model + viewer = castNonNull(viewer); + final IDocument document = viewer.getDocument(); + if (document == null) { + return; + } + internalListener.inputDocumentAboutToBeChanged(viewer.getDocument(), null); + internalListener.inputDocumentChanged(null, document); + } + } + + @Nullable + public IGrammar getGrammar() { + return grammar; + } + + @Nullable + public ITokenProvider getTokenProvider() { + return tokenProvider; + } + + public void setTheme(final ITokenProvider newTheme) { + final ITokenProvider oldTheme = this.tokenProvider; + if (!Objects.equals(oldTheme, newTheme) && grammar != null) { + this.tokenProvider = newTheme; + applyThemeEditor(); + final var viewer = this.viewer; + if (viewer == null) + return; + final IDocument document = viewer.getDocument(); + final ITMModel model = getTMModelManager().connect(document); + if (!(model instanceof TMDocumentModel)) { + return; + } + final TMDocumentModel docModel = (TMDocumentModel) model; + try { + colorize(new Region(0, document.getLength()), docModel); + } catch (final BadLocationException e) { + TMUIPlugin.log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); + } + } + } + + @Override + public void install(@Nullable ITextViewer viewer) { + viewer = this.viewer = castNonNull(viewer); + viewer.addTextInputListener(internalListener); + + final IDocument document = viewer.getDocument(); + if (document != null) { + internalListener.inputDocumentChanged(null, document); + } + final var themeChangeListener = this.themeChangeListener = new ThemeChangeListener(); + ThemeManager.getInstance().addPreferenceChangeListener(themeChangeListener); + } + + @Override + public void uninstall() { + final var viewer = castNonNull(this.viewer); + viewer.removeTextInputListener(internalListener); + // Ensure we uninstall all listeners + internalListener.inputDocumentAboutToBeChanged(viewer.getDocument(), null); + final var themeChangeListener = this.themeChangeListener; + if (themeChangeListener != null) { + ThemeManager.getInstance().removePreferenceChangeListener(themeChangeListener); + } + this.themeChangeListener = null; + } + + @Nullable + @Override + public IPresentationDamager getDamager(@Nullable final String contentType) { + return null; + } + + @Nullable + @Override + public IPresentationRepairer getRepairer(@Nullable final String contentType) { + return null; + } + + private ITMModelManager getTMModelManager() { + return TMUIPlugin.getTMModelManager(); + } + + void colorize(final IRegion damage, final TMDocumentModel model) throws BadLocationException { + final IDocument document = model.getDocument(); + final int fromLineNumber = document.getLineOfOffset(damage.getOffset()); + final int toLineNumber = document.getLineOfOffset(damage.getOffset() + damage.getLength()); + applyThemeEditorIfNeeded(); + // Refresh the UI Presentation + TMUIPlugin.trace("Render from: " + fromLineNumber + " to: " + toLineNumber); + final var presentation = new TextPresentation(damage, 1000); + Exception error = null; + try { + int lastStart = presentation.getExtent().getOffset(); + int length = 0; + boolean firstToken = true; + IToken lastToken = Token.UNDEFINED; + TextAttribute lastAttribute = getTokenTextAttribute(lastToken); + + List tokens = null; + for (int line = fromLineNumber; line <= toLineNumber; line++) { + tokens = model.getLineTokens(line); + if (tokens == null) { + // TextMate tokens was not computed for this line. + // This case comes from when the viewer is invalidated (by + // validation for instance) and textChanged is called. + // see https://github.com/eclipse/tm4e/issues/78 + TMUIPlugin.trace("TextMate tokens not available for line " + line); + break; + } + final int startLineOffset = document.getLineOffset(line); + for (int i = 0; i < tokens.size(); i++) { + final TMToken currentToken = tokens.get(i); + final TMToken nextToken = (i + 1 < tokens.size()) ? tokens.get(i + 1) : null; + int tokenStartIndex = currentToken.startIndex; + + if (isBeforeRegion(currentToken, startLineOffset, damage)) { + // The token is before the damage region + if (nextToken != null) { + if (isBeforeRegion(nextToken, startLineOffset, damage)) { + continue; // ignore it + } + tokenStartIndex = damage.getOffset() - startLineOffset; + } else { + tokenStartIndex = damage.getOffset() - startLineOffset; + final IToken token = toToken(currentToken); + lastAttribute = getTokenTextAttribute(token); + length += getTokenLengh(tokenStartIndex, nextToken, line, document); + firstToken = false; + // ignore it + continue; + } + } else if (isAfterRegion(currentToken, startLineOffset, damage)) { + // The token is after the damage region, stop the colorization process + break; + } + + final IToken token = toToken(currentToken); + final TextAttribute attribute = getTokenTextAttribute(token); + if (lastAttribute.equals(attribute)) { + length += getTokenLengh(tokenStartIndex, nextToken, line, document); + firstToken = false; + } else { + if (!firstToken) { + addRange(presentation, lastStart, length, lastAttribute); + } + firstToken = false; + lastToken = token; + lastAttribute = attribute; + lastStart = tokenStartIndex + startLineOffset; + length = getTokenLengh(tokenStartIndex, nextToken, line, document); + } + } + } + // adjust the length + length = Math.min(length, damage.getOffset() + damage.getLength() - lastStart); + addRange(presentation, lastStart, length, lastAttribute); + applyTextRegionCollection(presentation); + } catch (final Exception e) { + error = e; + TMUIPlugin.log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); + } finally { + fireColorize(presentation, error); + } + } + + /** + * Return true if the given token is before the given region and false + * otherwise. + * + * @param token + * @param startLineOffset + * @param damage + * + * @return + */ + private boolean isBeforeRegion(final TMToken token, final int startLineOffset, final IRegion damage) { + return token.startIndex + startLineOffset < damage.getOffset(); + } + + /** + * Return true if the given token is after the given region and false otherwise. + * + * @param t + * @param startLineOffset + * @param damage + * + * @return + */ + private boolean isAfterRegion(final TMToken t, final int startLineOffset, final IRegion damage) { + return t.startIndex + startLineOffset >= damage.getOffset() + damage.getLength(); + } + + private IToken toToken(final TMToken t) { + final var tokenProvider = this.tokenProvider; + if (tokenProvider != null) { + final IToken token = tokenProvider.getToken(t.type); + if (token != null) { + return token; + } + } + return defaultToken; + } + + private int getTokenLengh(final int tokenStartIndex, @Nullable final TMToken nextToken, final int line, + final IDocument document) + throws BadLocationException { + if (nextToken != null) { + return nextToken.startIndex - tokenStartIndex; + } + return document.getLineLength(line) - tokenStartIndex; + } + + /** + * Returns a text attribute encoded in the given token. If the token's data is + * not null and a text attribute it is assumed that it is the + * encoded text attribute. It returns the default text attribute if there is no + * encoded text attribute found. + * + * @param token + * the token whose text attribute is to be determined + * + * @return the token's text attribute + */ + protected TextAttribute getTokenTextAttribute(final IToken token) { + final Object data = token.getData(); + if (data instanceof TextAttribute) { + return (TextAttribute) data; + } + return fDefaultTextAttribute; + } + + /** + * Adds style information to the given text presentation. + * + * @param presentation + * the text presentation to be extended + * @param offset + * the offset of the range to be styled + * @param length + * the length of the range to be styled + * @param attr + * the attribute describing the style of the range to be styled + * @param lastLineStyleRanges + */ + protected void addRange(final TextPresentation presentation, final int offset, final int length, + @Nullable final TextAttribute attr) { + if (attr != null) { + final int style = attr.getStyle(); + final int fontStyle = style & (SWT.ITALIC | SWT.BOLD | SWT.NORMAL); + final StyleRange styleRange = new StyleRange(offset, length, attr.getForeground(), attr.getBackground(), + fontStyle); + styleRange.strikeout = (style & TextAttribute.STRIKETHROUGH) != 0; + styleRange.underline = (style & TextAttribute.UNDERLINE) != 0; + styleRange.font = attr.getFont(); + presentation.addStyleRange(styleRange); + } + } + + /** + * Applies the given text presentation to the text viewer the presentation + * reconciler is installed on. + * + * @param presentation + * the text presentation to be applied to the text viewer + */ + private void applyTextRegionCollection(final TextPresentation presentation) { + final var viewer = this.viewer; + if (viewer != null) { + viewer.changeTextPresentation(presentation, false); + } + } + + /** + * Add a TextMate presentation reconciler listener. + * + * @param listener + * the TextMate presentation reconciler listener to add. + */ + public void addTMPresentationReconcilerListener(final ITMPresentationReconcilerListener listener) { + synchronized (listeners) { + if (!listeners.contains(listener)) { + listeners.add(listener); + } + } + } + + /** + * Remove a TextMate presentation reconciler listener. + * + * @param listener + * the TextMate presentation reconciler listener to remove. + */ + public void removeTMPresentationReconcilerListener(final ITMPresentationReconcilerListener listener) { + synchronized (listeners) { + listeners.remove(listener); + } + } + + /** + * Fire colorize. + */ + private void fireColorize(final TextPresentation presentation, @Nullable final Throwable error) { + synchronized (listeners) { + for (final ITMPresentationReconcilerListener listener : listeners) { + listener.colorize(presentation, error); + } + } + } + + @Nullable + public static TMPresentationReconciler getTMPresentationReconciler(@Nullable final IEditorPart editorPart) { + if (editorPart == null) { + return null; + } + @Nullable + final ITextOperationTarget target = editorPart.getAdapter(ITextOperationTarget.class); + if (target instanceof ITextViewer) { + final ITextViewer textViewer = ((ITextViewer) target); + return TMPresentationReconciler.getTMPresentationReconciler(textViewer); + } + return null; + } + + /** + * Returns the {@link TMPresentationReconciler} of the given text viewer and null otherwise. + * + * @return the {@link TMPresentationReconciler} of the given text viewer and null otherwise. + */ + @Nullable + public static TMPresentationReconciler getTMPresentationReconciler(final ITextViewer textViewer) { + try { + final Field field = SourceViewer.class.getDeclaredField("fPresentationReconciler"); + if (field != null) { + field.trySetAccessible(); + final Object presentationReconciler = field.get(textViewer); + // field is IPresentationRecounciler, looking for TMPresentationReconciler implementation + return presentationReconciler instanceof TMPresentationReconciler + ? (TMPresentationReconciler) presentationReconciler + : null; + } + } catch (SecurityException | NoSuchFieldException e) { + // if SourceViewer class no longer has fPresentationReconciler or changes access level + TMUIPlugin.log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); + } catch (IllegalArgumentException | IllegalAccessException | NullPointerException + | ExceptionInInitializerError iae) { + // This should not be logged as an error. This is an expected possible outcome of field.get(textViewer). + // The method assumes ITextViewer is actually ISourceViewer, and specifically the SourceViewer + // implementation + // that was available at the current build. This code also works with any implementation that follows the + // internal structure if also an ITextViewer. + // If these assumptions are false, the method should return null. Logging causes repeat noise. + } + return null; + } + + /** + * Initialize foreground, background color, current line highlight from the current theme. + */ + private void applyThemeEditor() { + this.initializeViewerColors = false; + this.updateTextDecorations = false; + applyThemeEditorIfNeeded(); + } + + /** + * Initialize foreground, background color, current line highlight from the current theme if needed. + */ + private void applyThemeEditorIfNeeded() { + final var viewer = castNonNull(this.viewer); + final var tokenProvider = castNonNull(this.tokenProvider); + + if (!initializeViewerColors) { + final StyledText styledText = viewer.getTextWidget(); + ((ITheme) tokenProvider).initializeViewerColors(styledText); + initializeViewerColors = true; + } + if (updateTextDecorations) { + return; + } + try { + // Ugly code to update "current line highlight" : + // - get the PaintManager from the ITextViewer with reflection. + // - get the list of IPainter of PaintManager with reflection + // - loop for IPainter to retrieve CursorLinePainter which manages "current line + // highlight". + final PaintManager paintManager = ClassHelper.getFieldValue(viewer, "fPaintManager", TextViewer.class); + if (paintManager == null) { + return; + } + final List painters = ClassHelper.getFieldValue(paintManager, "fPainters", PaintManager.class); + if (painters == null) { + return; + } + for (final IPainter painter : painters) { + if (painter instanceof CursorLinePainter) { + // Update current line highlight + final Color background = tokenProvider.getEditorCurrentLineHighlight(); + if (background != null) { + ((CursorLinePainter) painter).setHighlightColor(background); + } + updateTextDecorations = true; + } + } + } catch (final Exception e) { + TMUIPlugin.log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); + } + } + + /** + * Set true if a {@link TMException} should be thrown if grammar or theme cannot + * be found and false otherwise. + * + * @param throwError + */ + public void setThrowError(final boolean throwError) { + this.throwError = throwError; + } + + /** + * Return true if a {@link TMException} should be thrown if grammar or theme + * cannot be found and false otherwise. + * + * @return true if a {@link TMException} should be thrown if grammar or theme + * cannot be found and false otherwise. + */ + public boolean isThrowError() { + return throwError; + } + + /** + * Returns true if the presentation reconciler is enabled (grammar and theme are + * available) and false otherwise. + * + * @return true if the presentation reconciler is enabled (grammar and theme are + * available) and false otherwise. + */ + + public boolean isEnabled() { + return enabled; + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/text/package-info.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/text/package-info.java new file mode 100644 index 000000000..b13c47863 --- /dev/null +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/text/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.ui.text; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/AbstractTokenProvider.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/AbstractTokenProvider.java index 4949e0754..a3d067b02 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/AbstractTokenProvider.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/AbstractTokenProvider.java @@ -1,20 +1,21 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.themes; - -/** - * Abstract class for {@link ITokenProvider}. - * - */ -public abstract class AbstractTokenProvider implements ITokenProvider { - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.themes; + +/** + * Abstract class for {@link ITokenProvider}. + * + * TODO remove? + */ +public abstract class AbstractTokenProvider implements ITokenProvider { + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ColorManager.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ColorManager.java index eacd5a860..d8ae1a467 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ColorManager.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ColorManager.java @@ -1,27 +1,31 @@ /** - * Copyright (c) 2015-2017 Angelo ZERR. + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * - * Contributors: - * Angelo Zerr - initial API and implementation + * Contributors: + * Angelo Zerr - initial API and implementation */ package org.eclipse.tm4e.ui.themes; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.widgets.Display; import org.eclipse.tm4e.core.theme.RGB; -import org.eclipse.tm4e.ui.utils.PreferenceUtils; +import org.eclipse.tm4e.ui.internal.utils.PreferenceUtils; import org.eclipse.ui.texteditor.AbstractTextEditor; -public class ColorManager { +import com.google.common.base.Splitter; + +public final class ColorManager { + + private static final Splitter BY_COMMA_SPLITTER = Splitter.on(','); private static final ColorManager INSTANCE = new ColorManager(); @@ -29,13 +33,12 @@ public static ColorManager getInstance() { return INSTANCE; } - private final Map fColorTable; + private final Map fColorTable = new HashMap<>(10); private ColorManager() { - fColorTable = new HashMap<>(10); } - public Color getColor(RGB rgb) { + public Color getColor(final RGB rgb) { Color color = fColorTable.get(rgb); if (color == null) { color = new Color(Display.getCurrent(), rgb.red, rgb.green, rgb.blue); @@ -45,51 +48,62 @@ public Color getColor(RGB rgb) { } public void dispose() { - Iterator e = fColorTable.values().iterator(); - while (e.hasNext()) { - e.next().dispose(); + for (final var c : fColorTable.values()) { + if (c != null) + c.dispose(); } } /** * Get the color from preferences store using a token. - * + * * @param tokenId - * name of the token + * name of the token + * * @return Color matching token */ - public Color getPreferenceEditorColor(String tokenId) { - return getColor(stringToRGB(PreferenceUtils.getEditorsPreferenceStore().get(tokenId, ""))); + @Nullable + public Color getPreferenceEditorColor(final String tokenId) { + final var prefStore = PreferenceUtils.getEditorsPreferenceStore(); + if(prefStore == null) + return null; + return getColor(stringToRGB(prefStore.get(tokenId, ""))); } /** * The method verifies that a color is defined in a preferences store using a token. - * + * * @param tokenId - * name of the token + * name of the token + * * @return color is user defined or not */ - public boolean isColorUserDefined(String tokenId) { - String systemDefaultToken = getSystemDefaultToken(tokenId); + public boolean isColorUserDefined(final String tokenId) { + final var prefStore = PreferenceUtils.getEditorsPreferenceStore(); + if(prefStore == null) + return false; - return systemDefaultToken != "" - ? !PreferenceUtils.getEditorsPreferenceStore().getBoolean(systemDefaultToken, true) - : true; // if system default token doesn't exists + final String systemDefaultToken = getSystemDefaultToken(tokenId); + + return "".equals(systemDefaultToken) || // returns true if system default token doesn't exists + !prefStore.getBoolean(systemDefaultToken, true); } /** * Get high priority color in text editors. * See Issue #176 * Priority: User defined > TM defined > Eclipse color - * + * * @param themeColor - * color defined in TM theme + * color defined in TM theme * @param tokenId - * name of the token for preferences store + * name of the token for preferences store + * * @return Highest priority color */ - public Color getPriorityColor(Color themeColor, String tokenId) { - Color prefColor = getPreferenceEditorColor(tokenId); + @Nullable + public Color getPriorityColor(@Nullable final Color themeColor, final String tokenId) { + final Color prefColor = getPreferenceEditorColor(tokenId); if (isColorUserDefined(tokenId)) { return prefColor; @@ -100,12 +114,13 @@ public Color getPriorityColor(Color themeColor, String tokenId) { /** * Returns a token for the system default value of the given token. - * + * * @param tokenId - * name of the token + * name of the token + * * @return system default token or empty string if doesn't exist */ - private String getSystemDefaultToken(String tokenId) { + private String getSystemDefaultToken(final String tokenId) { switch (tokenId) { case AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND: return AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT; @@ -122,16 +137,16 @@ private String getSystemDefaultToken(String tokenId) { /** * Convert String to RGB. - * + * * @param value - * string value of rgb + * string value of rgb + * * @return RGB value */ - private RGB stringToRGB(String value) { - String[] rgbValues = value.split(","); + private RGB stringToRGB(final String value) { + final String[] rgbValues = BY_COMMA_SPLITTER.splitToStream(value).toArray(String[]::new); return rgbValues.length == 3 ? new RGB(Integer.parseInt(rgbValues[0]), Integer.parseInt(rgbValues[1]), Integer.parseInt(rgbValues[2])) : new RGB(255, 255, 255); } - } diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ITheme.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ITheme.java index 3d3b25dd1..9024c1362 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ITheme.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ITheme.java @@ -1,69 +1,72 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.themes; - -import org.eclipse.swt.custom.StyledText; - -/** - * TextMate theme. - * - */ -public interface ITheme extends ITokenProvider { - - /** - * Returns the id of the theme. - * - * @return the id of the theme. - */ - String getId(); - - /** - * Returns the name of the theme. - * - * @return the name of the theme. - */ - String getName(); - - /** - * Returns the path of the theme. - * - * @return the path of the theme. - */ - String getPath(); - - /** - * Returns the plugin id. - * - * @return the plugin id - */ - String getPluginId(); - - /** - * Returns the theme content as CSS style sheet. - * - * @return the theme content as CSS style sheet. - */ - String toCSSStyleSheet(); - - boolean isDark(); - - boolean isDefault(); - - /** - * Initialize foreground, background color of the given {@link StyledText} with - * theme. - * - * @param textWidget - */ - void initializeViewerColors(StyledText styledText); - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.themes; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.swt.custom.StyledText; + +/** + * TextMate theme. + * + */ +public interface ITheme extends ITokenProvider { + + /** + * Returns the id of the theme. + * + * @return the id of the theme. + */ + String getId(); + + /** + * Returns the name of the theme. + * + * @return the name of the theme. + */ + String getName(); + + /** + * Returns the path of the theme. + * + * @return the path of the theme. + */ + @Nullable + String getPath(); + + /** + * Returns the plugin id. + * + * @return the plugin id + */ + @Nullable + String getPluginId(); + + /** + * Returns the theme content as CSS style sheet. + * + * @return the theme content as CSS style sheet. + */ + @Nullable + String toCSSStyleSheet(); + + boolean isDark(); + + boolean isDefault(); + + /** + * Initialize foreground, background color of the given {@link StyledText} with theme. + * + * @param styledText the StyledText to initialize + */ + void initializeViewerColors(StyledText styledText); + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/IThemeAssociation.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/IThemeAssociation.java index 95148a237..d10f6f3ea 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/IThemeAssociation.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/IThemeAssociation.java @@ -1,37 +1,39 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.themes; - -import org.eclipse.tm4e.registry.ITMDefinition; - -/** - * Theme association API. - * - */ -public interface IThemeAssociation extends ITMDefinition { - - /** - * Returns the TextMate theme id. - * - * @return the TextMate theme id. - */ - String getThemeId(); - - /** - * Returns the TextMate grammar scope linked to the theme id and null otherwise. - * - * @return the TextMate grammar scope to the theme id and null otherwise. - */ - String getScopeName(); - - boolean isWhenDark(); -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.themes; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tm4e.registry.ITMDefinition; + +/** + * Theme association API. + * + */ +public interface IThemeAssociation extends ITMDefinition { + + /** + * Returns the TextMate theme id. + * + * @return the TextMate theme id. + */ + String getThemeId(); + + /** + * Returns the TextMate grammar scope linked to the theme id and null otherwise. + * + * @return the TextMate grammar scope to the theme id and null otherwise. + */ + @Nullable + String getScopeName(); + + boolean isWhenDark(); +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/IThemeManager.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/IThemeManager.java index 20e09c006..b015188a2 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/IThemeManager.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/IThemeManager.java @@ -1,143 +1,145 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.themes; - -import org.eclipse.swt.graphics.RGB; -import org.osgi.service.prefs.BackingStoreException; - -/** - * TextMate theme manager API. - * - */ -public interface IThemeManager { - - /** - * Register the given theme. - * - * @param theme - * to unregister. - */ - void registerTheme(ITheme theme); - - /** - * Unregister the given theme. - * - * @param theme - * to unregister. - */ - void unregisterTheme(ITheme theme); - - /** - * Returns the {@link ITheme} by the theme id. - * - * @param themeId - * the theme id. - * @return the {@link ITheme} by the theme id. - */ - ITheme getThemeById(String themeId); - - /** - * Returns the list of TextMate themes. - * - * @return the list of TextMate themes. - */ - ITheme[] getThemes(); - - /** - * Returns the default theme. - * - * @return the default theme. - */ - ITheme getDefaultTheme(); - - /** - * Returns the list of TextMate themes for the given eclipse theme id. - * - * @return the list of TextMate themes for the given eclipse theme id. - */ - ITheme[] getThemes(boolean dark); - - /** - * Returns the TextMate theme {@link ITheme} for the given TextMate grammar - * scopeName and E4 Theme eclipseThemeId. - * - * @param scopeName - * the TextMate grammar - * @param eclipseThemeId - * the E4 Theme. - * @return the TextMate theme {@link ITheme} for the given TextMate grammar - * scopeName and E4 Theme eclipseThemeId. - */ - ITheme getThemeForScope(String scopeName, boolean dark); - - /** - * Returns the TextMate theme {@link ITheme} for the given TextMate grammar - * scopeName and default E4 Theme. - * - * @param scopeName - * @return the TextMate theme {@link ITheme} for the given TextMate grammar - * scopeName and default E4 Theme. - */ - ITheme getThemeForScope(String scopeName); - - /** - * Register the given theme association. - * - * @param association - * to register. - */ - void registerThemeAssociation(IThemeAssociation association); - - /** - * Unregister the given theme association. - * - * @param association - * to unregister. - */ - void unregisterThemeAssociation(IThemeAssociation association); - - /** - * Returns list of all theme associations. - * - * @return list of all theme associations. - */ - IThemeAssociation[] getAllThemeAssociations(); - - /** - * Returns the theme associations for the given TextMate grammar - * scopeName. - * - * @param scopeName - * @return the theme associations for the given TextMate grammar - * scopeName. - */ - IThemeAssociation[] getThemeAssociationsForScope(String scopeName); - - /** - * Save the themes definitions. - * - * @throws BackingStoreException - */ - void save() throws BackingStoreException; - - boolean isDarkEclipseTheme(); - - boolean isDarkEclipseTheme(String eclipseThemeId); - - /** - * - * @param scopeName - * @param background - * @return the theme that will fit best for the defined background color - */ - ITokenProvider getThemeForScope(String scopeName, RGB background); -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.themes; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.swt.graphics.RGB; +import org.osgi.service.prefs.BackingStoreException; + +/** + * TextMate theme manager API. + * + */ +public interface IThemeManager { + + /** + * Register the given theme. + * + * @param theme + * to unregister. + */ + void registerTheme(ITheme theme); + + /** + * Unregister the given theme. + * + * @param theme + * to unregister. + */ + void unregisterTheme(ITheme theme); + + /** + * Returns the {@link ITheme} by the theme id. + * + * @param themeId + * the theme id. + * @return the {@link ITheme} by the theme id. + */ + @Nullable + ITheme getThemeById(String themeId); + + /** + * Returns the list of TextMate themes. + * + * @return the list of TextMate themes. + */ + ITheme[] getThemes(); + + /** + * Returns the default theme. + * + * @return the default theme. + */ + ITheme getDefaultTheme(); + + /** + * Returns the list of TextMate themes for the given eclipse theme id. + * + * @return the list of TextMate themes for the given eclipse theme id. + */ + ITheme[] getThemes(boolean dark); + + /** + * Returns the TextMate theme {@link ITheme} for the given TextMate grammar + * scopeName and E4 Theme eclipseThemeId. + * + * @param scopeName + * the TextMate grammar + * @param eclipseThemeId + * the E4 Theme. + * @return the TextMate theme {@link ITheme} for the given TextMate grammar + * scopeName and E4 Theme eclipseThemeId. + */ + ITheme getThemeForScope(String scopeName, boolean dark); + + /** + * Returns the TextMate theme {@link ITheme} for the given TextMate grammar + * scopeName and default E4 Theme. + * + * @param scopeName + * @return the TextMate theme {@link ITheme} for the given TextMate grammar + * scopeName and default E4 Theme. + */ + ITheme getThemeForScope(String scopeName); + + /** + * Register the given theme association. + * + * @param association + * to register. + */ + void registerThemeAssociation(IThemeAssociation association); + + /** + * Unregister the given theme association. + * + * @param association + * to unregister. + */ + void unregisterThemeAssociation(IThemeAssociation association); + + /** + * Returns list of all theme associations. + * + * @return list of all theme associations. + */ + IThemeAssociation[] getAllThemeAssociations(); + + /** + * Returns the theme associations for the given TextMate grammar + * scopeName. + * + * @param scopeName + * @return the theme associations for the given TextMate grammar + * scopeName. + */ + IThemeAssociation[] getThemeAssociationsForScope(String scopeName); + + /** + * Save the themes definitions. + * + * @throws BackingStoreException + */ + void save() throws BackingStoreException; + + boolean isDarkEclipseTheme(); + + boolean isDarkEclipseTheme(@Nullable String eclipseThemeId); + + /** + * + * @param scopeName + * @param background + * @return the theme that will fit best for the defined background color + */ + ITokenProvider getThemeForScope(String scopeName, RGB background); +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ITokenProvider.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ITokenProvider.java index c3e5e54e7..36c519998 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ITokenProvider.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ITokenProvider.java @@ -1,40 +1,47 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.themes; - -import org.eclipse.jface.text.rules.IToken; -import org.eclipse.swt.graphics.Color; - -/** - * Provider to retrieve Eclipse {@link IToken} from the TextMate token type. - * - */ -public interface ITokenProvider { - - /** - * Returns the Eclipse {@link IToken} from the given type and null otherwise. - * - * @param type - * @return the Eclipse {@link IToken} from the given type and null otherwise. - */ - IToken getToken(String type); - - Color getEditorBackground(); - - Color getEditorForeground(); - - Color getEditorSelectionBackground(); - - Color getEditorSelectionForeground(); - - Color getEditorCurrentLineHighlight(); -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.themes; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.swt.graphics.Color; + +/** + * Provider to retrieve Eclipse {@link IToken} from the TextMate token type. + * + */ +public interface ITokenProvider { + + /** + * Returns the Eclipse {@link IToken} from the given type and null otherwise. + * + * @param type + * @return the Eclipse {@link IToken} from the given type and null otherwise. + */ + @Nullable + IToken getToken(String type); + + @Nullable + Color getEditorBackground(); + + @Nullable + Color getEditorForeground(); + + @Nullable + Color getEditorSelectionBackground(); + + @Nullable + Color getEditorSelectionForeground(); + + @Nullable + Color getEditorCurrentLineHighlight(); +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/Theme.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/Theme.java index df2873c18..af99ef766 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/Theme.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/Theme.java @@ -1,180 +1,190 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.themes; - -import java.io.InputStream; - -import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.jface.text.rules.IToken; -import org.eclipse.swt.custom.StyledText; -import org.eclipse.swt.graphics.Color; -import org.eclipse.tm4e.registry.TMResource; -import org.eclipse.tm4e.registry.XMLConstants; -import org.eclipse.tm4e.ui.internal.preferences.PreferenceConstants; -import org.eclipse.tm4e.ui.themes.css.CSSTokenProvider; -import org.eclipse.ui.texteditor.AbstractTextEditor; - -/** - * {@link ITheme} implementation. - * - */ -public class Theme extends TMResource implements ITheme { - - private static final String DARK_ATTR = "dark"; - private static final String DEFAULT_ATTR = "default"; - - private ITokenProvider tokenProvider; - - private String id; - private String name; - private boolean dark; - private boolean isDefault; - - /** - * Constructor for user preferences (loaded from Json with Gson). - */ - public Theme() { - super(); - } - - /** - * Constructor for extension point. - * - * @param element - */ - public Theme(String id, String path, String name, boolean dark, boolean isDefault) { - super(path); - this.id = id; - this.name = name; - this.dark = dark; - this.isDefault = isDefault; - } - - public Theme(IConfigurationElement ce) { - super(ce); - id = ce.getAttribute(XMLConstants.ID_ATTR); - name = ce.getAttribute(XMLConstants.NAME_ATTR); - dark = Boolean.parseBoolean(ce.getAttribute(DARK_ATTR)); - isDefault = Boolean.parseBoolean(ce.getAttribute(DEFAULT_ATTR)); - } - - @Override - public String getId() { - return id; - } - - @Override - public String getName() { - return name; - } - - @Override - public IToken getToken(String type) { - ITokenProvider provider = getTokenProvider(); - return provider != null ? provider.getToken(type) : null; - } - - @Override - public Color getEditorForeground() { - ITokenProvider provider = getTokenProvider(); - Color themeColor = provider != null ? provider.getEditorForeground() : null; - return ColorManager.getInstance() - .getPriorityColor(themeColor, AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND); - } - - @Override - public Color getEditorBackground() { - ITokenProvider provider = getTokenProvider(); - Color themeColor = provider != null ? provider.getEditorBackground() : null; - return ColorManager.getInstance() - .getPriorityColor(themeColor, AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND); - } - - @Override - public Color getEditorSelectionForeground() { - ITokenProvider provider = getTokenProvider(); - Color themeColor = provider != null ? provider.getEditorSelectionForeground() : null; - return ColorManager.getInstance() - .getPriorityColor(themeColor, AbstractTextEditor.PREFERENCE_COLOR_SELECTION_FOREGROUND); - } - - @Override - public Color getEditorSelectionBackground() { - ITokenProvider provider = getTokenProvider(); - Color themeColor = provider != null ? provider.getEditorSelectionBackground() : null; - return ColorManager.getInstance() - .getPriorityColor(themeColor, AbstractTextEditor.PREFERENCE_COLOR_SELECTION_BACKGROUND); - } - - @Override - public Color getEditorCurrentLineHighlight() { - ITokenProvider provider = getTokenProvider(); - Color themeColor = provider != null ? provider.getEditorCurrentLineHighlight() : null; - ColorManager manager = ColorManager.getInstance(); - return manager.isColorUserDefined(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND) - ? manager.getPreferenceEditorColor(PreferenceConstants.EDITOR_CURRENTLINE_HIGHLIGHT) - : themeColor; - } - - private ITokenProvider getTokenProvider() { - if (tokenProvider == null) { - try { - InputStream in = super.getInputStream(); - if (in == null) { - return null; - } - tokenProvider = new CSSTokenProvider(in); - } catch (Exception e) { - e.printStackTrace(); - } - } - return tokenProvider; - } - - @Override - public String toCSSStyleSheet() { - return super.getResourceContent(); - } - - @Override - public boolean isDark() { - return dark; - } - - @Override - public boolean isDefault() { - return isDefault; - } - - @Override - public void initializeViewerColors(StyledText styledText) { - Color color = getEditorBackground(); - if (color != null) { - styledText.setBackground(color); - } - - color = getEditorForeground(); - if (color != null) { - styledText.setForeground(color); - } - - color = getEditorSelectionBackground(); - if (color != null) { - styledText.setSelectionBackground(color); - } - - color = getEditorSelectionForeground(); - if (color != null) { - styledText.setSelectionForeground(color); - } - } -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.themes; + +import java.io.InputStream; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.Color; +import org.eclipse.tm4e.registry.TMResource; +import org.eclipse.tm4e.registry.XMLConstants; +import org.eclipse.tm4e.ui.internal.preferences.PreferenceConstants; +import org.eclipse.tm4e.ui.themes.css.CSSTokenProvider; +import org.eclipse.ui.texteditor.AbstractTextEditor; + +/** + * {@link ITheme} implementation. + * + */ +public class Theme extends TMResource implements ITheme { + + private static final String DARK_ATTR = "dark"; + private static final String DEFAULT_ATTR = "default"; + + @Nullable + private ITokenProvider tokenProvider; + + private String id; + private String name; + private boolean dark; + private boolean isDefault; + + /** + * Constructor for user preferences (loaded from Json with Gson). + */ + public Theme() { + name = ""; + id = ""; + } + + /** + * Constructor for extension point. + * + * @param id + */ + public Theme(final String id, final String path, final String name, final boolean dark, final boolean isDefault) { + super(path); + this.id = id; + this.name = name; + this.dark = dark; + this.isDefault = isDefault; + } + + public Theme(final IConfigurationElement ce) { + super(ce); + id = ce.getAttribute(XMLConstants.ID_ATTR); + name = ce.getAttribute(XMLConstants.NAME_ATTR); + dark = Boolean.parseBoolean(ce.getAttribute(DARK_ATTR)); + isDefault = Boolean.parseBoolean(ce.getAttribute(DEFAULT_ATTR)); + } + + @Override + public String getId() { + return id; + } + + @Override + public String getName() { + return name; + } + + @Nullable + @Override + public IToken getToken(final String type) { + final ITokenProvider provider = getTokenProvider(); + return provider != null ? provider.getToken(type) : null; + } + + @Nullable + @Override + public Color getEditorForeground() { + final ITokenProvider provider = getTokenProvider(); + final Color themeColor = provider != null ? provider.getEditorForeground() : null; + return ColorManager.getInstance() + .getPriorityColor(themeColor, AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND); + } + + @Nullable + @Override + public Color getEditorBackground() { + final ITokenProvider provider = getTokenProvider(); + final Color themeColor = provider != null ? provider.getEditorBackground() : null; + return ColorManager.getInstance() + .getPriorityColor(themeColor, AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND); + } + + @Nullable + @Override + public Color getEditorSelectionForeground() { + final ITokenProvider provider = getTokenProvider(); + final Color themeColor = provider != null ? provider.getEditorSelectionForeground() : null; + return ColorManager.getInstance() + .getPriorityColor(themeColor, AbstractTextEditor.PREFERENCE_COLOR_SELECTION_FOREGROUND); + } + + @Nullable + @Override + public Color getEditorSelectionBackground() { + final ITokenProvider provider = getTokenProvider(); + final Color themeColor = provider != null ? provider.getEditorSelectionBackground() : null; + return ColorManager.getInstance() + .getPriorityColor(themeColor, AbstractTextEditor.PREFERENCE_COLOR_SELECTION_BACKGROUND); + } + + @Nullable + @Override + public Color getEditorCurrentLineHighlight() { + final ITokenProvider provider = getTokenProvider(); + final Color themeColor = provider != null ? provider.getEditorCurrentLineHighlight() : null; + final ColorManager manager = ColorManager.getInstance(); + return manager.isColorUserDefined(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND) + ? manager.getPreferenceEditorColor(PreferenceConstants.EDITOR_CURRENTLINE_HIGHLIGHT) + : themeColor; + } + + @Nullable + private ITokenProvider getTokenProvider() { + if (tokenProvider == null) { + try (InputStream in = super.getInputStream()) { + if (in == null) { + return null; + } + tokenProvider = new CSSTokenProvider(in); + } catch (final Exception e) { + e.printStackTrace(); + } + } + return tokenProvider; + } + + @Nullable + @Override + public String toCSSStyleSheet() { + return super.getResourceContent(); + } + + @Override + public boolean isDark() { + return dark; + } + + @Override + public boolean isDefault() { + return isDefault; + } + + @Override + public void initializeViewerColors(final StyledText styledText) { + Color color = getEditorBackground(); + if (color != null) { + styledText.setBackground(color); + } + + color = getEditorForeground(); + if (color != null) { + styledText.setForeground(color); + } + + color = getEditorSelectionBackground(); + if (color != null) { + styledText.setSelectionBackground(color); + } + + color = getEditorSelectionForeground(); + if (color != null) { + styledText.setSelectionForeground(color); + } + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ThemeAssociation.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ThemeAssociation.java index 69783db51..bf5b18224 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ThemeAssociation.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ThemeAssociation.java @@ -1,139 +1,124 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -/** - * Copyright (c) 2015-2017 Angelo ZERR. + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.themes; - -/** - * Copyright (c) 2015-2017 Angelo ZERR. + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.themes; + +import java.util.Objects; + +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -import org.eclipse.core.runtime.IConfigurationElement; - -/** - * Theme association implementation. - * - */ -public class ThemeAssociation implements IThemeAssociation { - - private static final String THEME_ID_ATTR = "themeId"; //$NON-NLS-1$ - private static final String SCOPE_NAME_ATTR = "scopeName"; //$NON-NLS-1$ - private static final String WHEN_DARK_ATTR = "whenDark"; //$NON-NLS-1$ - - private String themeId; - private String scopeName; - private boolean whenDark; - private String pluginId; - - /** - * Constructor for user preferences (loaded from Json with Gson). - */ - public ThemeAssociation() { - super(); - } - - /** - * Constructor to register theme associations for a given scope name. - * - * @param themeId - * @param eclipseThemeId - * @param scopeName - */ - public ThemeAssociation(String themeId, String scopeName, boolean whenDark) { - this.themeId = themeId; - this.scopeName = scopeName; - this.whenDark = whenDark; - } - - public ThemeAssociation(IConfigurationElement ce) { - this(ce.getAttribute(THEME_ID_ATTR), ce.getAttribute(SCOPE_NAME_ATTR), - "true".equals(ce.getAttribute(WHEN_DARK_ATTR))); - this.pluginId = ce.getNamespaceIdentifier(); - } - - @Override - public String getPluginId() { - return pluginId; - } - - @Override - public String getThemeId() { - return themeId; - } - - @Override - public String getScopeName() { - return scopeName; - } - - @Override - public boolean isWhenDark() { - return whenDark; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((pluginId == null) ? 0 : pluginId.hashCode()); - result = prime * result + ((scopeName == null) ? 0 : scopeName.hashCode()); - result = prime * result + ((themeId == null) ? 0 : themeId.hashCode()); - result = prime * result + (whenDark ? 1231 : 1237); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - ThemeAssociation other = (ThemeAssociation) obj; - if (pluginId == null) { - if (other.pluginId != null) - return false; - } else if (!pluginId.equals(other.pluginId)) - return false; - if (scopeName == null) { - if (other.scopeName != null) - return false; - } else if (!scopeName.equals(other.scopeName)) - return false; - if (themeId == null) { - if (other.themeId != null) - return false; - } else if (!themeId.equals(other.themeId)) - return false; - if (whenDark != other.whenDark) - return false; - return true; - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.jdt.annotation.Nullable; + +/** + * Theme association implementation. + */ +public class ThemeAssociation implements IThemeAssociation { + + private static final String THEME_ID_ATTR = "themeId"; //$NON-NLS-1$ + private static final String SCOPE_NAME_ATTR = "scopeName"; //$NON-NLS-1$ + private static final String WHEN_DARK_ATTR = "whenDark"; //$NON-NLS-1$ + + private String themeId; + + @Nullable + private String scopeName; + + private boolean whenDark; + + @Nullable + private String pluginId; + + /** + * Constructor for user preferences (loaded from Json with Gson). + */ + public ThemeAssociation() { + themeId = ""; + } + + /** + * Constructor to register theme associations for a given scope name. + */ + public ThemeAssociation(final String themeId, final String scopeName, final boolean whenDark) { + this.themeId = themeId; + this.scopeName = scopeName; + this.whenDark = whenDark; + } + + public ThemeAssociation(final IConfigurationElement ce) { + this(ce.getAttribute(THEME_ID_ATTR), ce.getAttribute(SCOPE_NAME_ATTR), + "true".equals(ce.getAttribute(WHEN_DARK_ATTR))); + this.pluginId = ce.getNamespaceIdentifier(); + } + + @Nullable + @Override + public String getPluginId() { + return pluginId; + } + + @Override + public String getThemeId() { + return themeId; + } + + @Nullable + @Override + public String getScopeName() { + return scopeName; + } + + @Override + public boolean isWhenDark() { + return whenDark; + } + + @Override + public int hashCode() { + return Objects.hash(pluginId, scopeName, themeId, whenDark); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ThemeAssociation other = (ThemeAssociation) obj; + return Objects.equals(pluginId, other.pluginId) + && Objects.equals(scopeName, other.scopeName) + && Objects.equals(themeId, other.themeId) + && whenDark == other.whenDark; + } + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ThemeIdConstants.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ThemeIdConstants.java index a44e152c3..8703f5b0a 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ThemeIdConstants.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/ThemeIdConstants.java @@ -1,25 +1,25 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.themes; - -/** - * Default TextMate theme ID constants. - * - */ -public interface ThemeIdConstants { - - public static final String Light = "org.eclipse.tm4e.ui.themes.Light"; - public static final String Monokai = "org.eclipse.tm4e.ui.themes.Monokai"; - public static final String SolarizedLight = "org.eclipse.tm4e.ui.themes.SolarizedLight"; - public static final String Dark = "org.eclipse.tm4e.ui.themes.Dark"; - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.themes; + +/** + * Default TextMate theme ID constants. + * + */ +public interface ThemeIdConstants { + + String Light = "org.eclipse.tm4e.ui.themes.Light"; + String Monokai = "org.eclipse.tm4e.ui.themes.Monokai"; + String SolarizedLight = "org.eclipse.tm4e.ui.themes.SolarizedLight"; + String Dark = "org.eclipse.tm4e.ui.themes.Dark"; + +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/css/CSSTokenProvider.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/css/CSSTokenProvider.java index cd84260d0..83d022a1c 100644 --- a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/css/CSSTokenProvider.java +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/css/CSSTokenProvider.java @@ -1,126 +1,136 @@ -/** - * Copyright (c) 2015-2017 Angelo ZERR. +/** + * Copyright (c) 2015-2017 Angelo ZERR. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Angelo Zerr - initial API and implementation - */ -package org.eclipse.tm4e.ui.themes.css; - -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.jface.text.TextAttribute; -import org.eclipse.jface.text.rules.IToken; -import org.eclipse.jface.text.rules.Token; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Color; -import org.eclipse.tm4e.core.theme.IStyle; -import org.eclipse.tm4e.core.theme.RGB; -import org.eclipse.tm4e.core.theme.css.CSSParser; -import org.eclipse.tm4e.ui.TMUIPlugin; -import org.eclipse.tm4e.ui.themes.AbstractTokenProvider; -import org.eclipse.tm4e.ui.themes.ColorManager; - -public class CSSTokenProvider extends AbstractTokenProvider { - - private Map tokenMaps; - private CSSParser parser; - - public CSSTokenProvider(InputStream in) { - tokenMaps = new HashMap<>(); - try { - parser = new CSSParser(in); - for (IStyle style : parser.getStyles()) { - RGB color = style.getColor(); - if (color != null) { - int s = SWT.NORMAL; - if (style.isBold()) { - s = s | SWT.BOLD; - } - if (style.isItalic()) { - s = s | SWT.ITALIC; - } - if (style.isUnderline()) { - s = s | TextAttribute.UNDERLINE; - } - if (style.isStrikeThrough()) { - s = s | TextAttribute.STRIKETHROUGH; - } - tokenMaps.put(style, - new Token(new TextAttribute(ColorManager.getInstance().getColor(color), null, s))); - } - } - } catch (Exception e) { - TMUIPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); - } - } - - @Override - public IToken getToken(String type) { - if (type == null) { - return null; - } - IStyle style = parser.getBestStyle(type.split("[.]")); - if (style != null) { - IToken t = tokenMaps.get(style); - if (t != null) { - return t; - } - } - return null; - } - - @Override - public Color getEditorForeground() { - IStyle style = parser.getBestStyle("editor"); - if (style != null && style.getColor() != null) { - return ColorManager.getInstance().getColor(style.getColor()); - } - return null; - } - - @Override - public Color getEditorBackground() { - IStyle style = parser.getBestStyle("editor"); - if (style != null && style.getBackgroundColor() != null) { - return ColorManager.getInstance().getColor(style.getBackgroundColor()); - } - return null; - } - - @Override - public Color getEditorSelectionForeground() { - IStyle style = parser.getBestStyle("editor", "selection"); - if (style != null && style.getColor() != null) { - return ColorManager.getInstance().getColor(style.getColor()); - } - return null; - } - - @Override - public Color getEditorSelectionBackground() { - IStyle style = parser.getBestStyle("editor", "selection"); - if (style != null && style.getBackgroundColor() != null) { - return ColorManager.getInstance().getColor(style.getBackgroundColor()); - } - return null; - } - - @Override - public Color getEditorCurrentLineHighlight() { - IStyle style = parser.getBestStyle("editor", "lineHighlight"); - if (style != null && style.getBackgroundColor() != null) { - return ColorManager.getInstance().getColor(style.getBackgroundColor()); - } - return null; - } - -} + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Angelo Zerr - initial API and implementation + */ +package org.eclipse.tm4e.ui.themes.css; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.tm4e.core.theme.IStyle; +import org.eclipse.tm4e.core.theme.RGB; +import org.eclipse.tm4e.core.theme.css.CSSParser; +import org.eclipse.tm4e.ui.TMUIPlugin; +import org.eclipse.tm4e.ui.themes.AbstractTokenProvider; +import org.eclipse.tm4e.ui.themes.ColorManager; + +import com.google.common.base.Splitter; + +public class CSSTokenProvider extends AbstractTokenProvider { + + private static final Splitter BY_DOT_SPLITTER = Splitter.on('.'); + + private final Map tokenMaps = new HashMap<>(); + + @Nullable + private CSSParser parser; + + public CSSTokenProvider(final InputStream in) { + try { + parser = new CSSParser(in); + for (final IStyle style : parser.getStyles()) { + final RGB color = style.getColor(); + if (color != null) { + int s = SWT.NORMAL; + if (style.isBold()) { + s = s | SWT.BOLD; + } + if (style.isItalic()) { + s = s | SWT.ITALIC; + } + if (style.isUnderline()) { + s = s | TextAttribute.UNDERLINE; + } + if (style.isStrikeThrough()) { + s = s | TextAttribute.STRIKETHROUGH; + } + tokenMaps.put(style, + new Token(new TextAttribute(ColorManager.getInstance().getColor(color), null, s))); + } + } + } catch (final Exception e) { + TMUIPlugin.log(new Status(IStatus.ERROR, TMUIPlugin.PLUGIN_ID, e.getMessage(), e)); + } + } + + @Nullable + @Override + public IToken getToken(@Nullable final String type) { + if (type == null) + return null; + + final var parser = this.parser; + if (parser == null) + return null; + + final IStyle style = parser.getBestStyle(BY_DOT_SPLITTER.splitToStream(type).toArray(String[]::new)); + if (style == null) + return null; + + return tokenMaps.get(style); + } + + @Nullable + private Color getColor(final boolean isForeground, final String... styles) { + final var parser = this.parser; + if (parser == null) + return null; + + final var style = parser.getBestStyle(styles); + if (style == null) + return null; + + final var rgb = isForeground ? style.getColor() : style.getBackgroundColor(); + if (rgb == null) + return null; + + return ColorManager.getInstance().getColor(rgb); + } + + @Nullable + @Override + public Color getEditorForeground() { + return getColor(true, "editor"); + } + + @Nullable + @Override + public Color getEditorBackground() { + return getColor(false, "editor"); + } + + @Nullable + @Override + public Color getEditorSelectionForeground() { + return getColor(true, "editor", "selection"); + } + + @Nullable + @Override + public Color getEditorSelectionBackground() { + return getColor(false, "editor", "selection"); + + } + + @Nullable + @Override + public Color getEditorCurrentLineHighlight() { + return getColor(false, "editor", "lineHighlight"); + } +} diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/css/package-info.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/css/package-info.java new file mode 100644 index 000000000..6a88c3457 --- /dev/null +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/css/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.ui.themes.css; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/package-info.java b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/package-info.java new file mode 100644 index 000000000..02ae596cf --- /dev/null +++ b/org.eclipse.tm4e.ui/src/main/java/org/eclipse/tm4e/ui/themes/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package org.eclipse.tm4e.ui.themes; + +import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/model/DocumentLineListTest.java b/org.eclipse.tm4e.ui/src/test/java/org/eclipse/tm4e/ui/internal/model/DocumentLineListTest.java similarity index 91% rename from org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/model/DocumentLineListTest.java rename to org.eclipse.tm4e.ui/src/test/java/org/eclipse/tm4e/ui/internal/model/DocumentLineListTest.java index 0a76fae71..f0e81dd51 100644 --- a/org.eclipse.tm4e.ui.tests/src/test/java/org/eclipse/tm4e/ui/internal/model/DocumentLineListTest.java +++ b/org.eclipse.tm4e.ui/src/test/java/org/eclipse/tm4e/ui/internal/model/DocumentLineListTest.java @@ -9,18 +9,18 @@ * Contributors: * Angelo Zerr - initial API and implementation */ -package org.eclipse.tm4e.ui.internal.model; - +package org.eclipse.tm4e.ui.internal.model; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import org.eclipse.jface.text.Document; import org.junit.jupiter.api.Test; - -public class DocumentLineListTest { - + +class DocumentLineListTest { + @Test - public void testMultiLineChange() { + void testMultiLineChange() { Document document = new Document(); DocumentLineList lineList = new DocumentLineList(document); @@ -31,5 +31,5 @@ public void testMultiLineChange() { document.set("a\nb"); assertEquals(2, lineList.getNumberOfLines()); } - -} + +} diff --git a/pom.xml b/pom.xml index 93a59b253..6650f2840 100644 --- a/pom.xml +++ b/pom.xml @@ -11,10 +11,10 @@ UTF-8 - 2.5.0 + 3.0.0-SNAPSHOT ../target/jacoco.exec scm:git:https://github.com/eclipse/tm4e.git - true + error Eclipse TM4E project @@ -75,7 +75,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M5 + 3.0.0-M6 test @@ -84,11 +84,18 @@ + + + org.junit.jupiter + junit-jupiter-engine + 5.8.2 + + org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.10.1 11 11 @@ -123,20 +130,6 @@ - - org.eclipse.cbi.maven.plugins - eclipse-jarsigner-plugin - 1.3.2 - - - sign - package - - sign - - - - org.eclipse.tycho tycho-p2-plugin @@ -144,7 +137,7 @@ attach-p2-metadata - package + verify p2-metadata @@ -181,6 +174,7 @@ jgit pom.xml + ${jgit.dirtyWorkingTree} @@ -205,7 +199,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.3.1 + 3.4.0 true @@ -213,7 +207,7 @@ org.jacoco jacoco-maven-plugin - 0.8.7 + 0.8.8 prepare-agent @@ -271,10 +265,25 @@ - packAndSign - - false - + sign + + + + org.eclipse.cbi.maven.plugins + eclipse-jarsigner-plugin + 1.3.2 + + + jarsigner + package + + sign + + + + + + @@ -287,6 +296,19 @@ true + + dash-licenses-snapshots + https://repo.eclipse.org/content/repositories/dash-licenses-snapshots/ + + true + + + + tycho-snapshots + https://repo.eclipse.org/content/repositories/tycho-snapshots/ + + true + + - diff --git a/target-platform/tm4e-target.target b/target-platform/tm4e-target.target index 6b50e5689..b4c3269eb 100644 --- a/target-platform/tm4e-target.target +++ b/target-platform/tm4e-target.target @@ -1,28 +1,47 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + org.jruby.joni + joni + 2.1.43 + jar + + + + + + \ No newline at end of file