This is an automated email from the ASF dual-hosted git repository.
jlahoda pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-netbeans.git
The following commit(s) were added to refs/heads/master by this push:
new 93192ad Support for TextMate grammars (from VS Code)
93192ad is described below
commit 93192ad1b8b586d339ebc0afa8e24712ee89e1af
Author: Jan Lahoda <[email protected]>
AuthorDate: Tue Jan 29 22:39:34 2019 +0100
Support for TextMate grammars (from VS Code)
---
ide/textmate.lexer/arch.xml | 1115 ++++++++++++++++++++
ide/textmate.lexer/build.xml | 23 +
ide/textmate.lexer/external/binaries-list | 19 +
.../external/jcodings-1.0.41-license.txt | 23 +
.../external/joni-2.1.11-license.txt | 27 +
...clipse.tm4e.core_0.2.0.201809031154-license.txt | 209 ++++
ide/textmate.lexer/manifest.mf | 7 +
ide/textmate.lexer/nbproject/project.properties | 23 +
ide/textmate.lexer/nbproject/project.xml | 202 ++++
.../modules/textmate/lexer/Bundle.properties | 17 +
.../modules/textmate/lexer/SyntaxHighlighting.java | 862 +++++++++++++++
.../modules/textmate/lexer/TextmateLexer.java | 110 ++
.../modules/textmate/lexer/TextmateTokenId.java | 141 +++
.../textmate/lexer/resources/Bundle.properties | 17 +
.../textmate/lexer/resources/fontsColors.xml | 56 +
.../modules/textmate/lexer/resources/layer.xml | 40 +
.../modules/textmate/lexer/TextmateLexerTest.java | 171 +++
nbbuild/cluster.properties | 1 +
nbbuild/licenses/MIT-jruby | 21 +
nbbuild/licenses/names.properties | 1 +
20 files changed, 3085 insertions(+)
diff --git a/ide/textmate.lexer/arch.xml b/ide/textmate.lexer/arch.xml
new file mode 100644
index 0000000..9e275fe
--- /dev/null
+++ b/ide/textmate.lexer/arch.xml
@@ -0,0 +1,1115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<!DOCTYPE api-answers PUBLIC "-//NetBeans//DTD Arch Answers//EN"
"../../nbbuild/antsrc/org/netbeans/nbbuild/Arch.dtd" [
+ <!ENTITY api-questions SYSTEM
"../../nbbuild/antsrc/org/netbeans/nbbuild/Arch-api-questions.xml">
+]>
+
+<api-answers
+ question-version="1.29"
+ author="[email protected]"
+>
+
+ &api-questions;
+
+
+<!--
+ <question id="arch-overall" when="init">
+ Describe the overall architecture.
+ <hint>
+ What will be API for
+ <a
href="http://wiki.netbeans.org/API_Design#Separate_API_for_clients_from_support_API">
+ clients and what support API</a>?
+ What parts will be pluggable?
+ How will plug-ins be registered? Please use <code><api
type="export"/></code>
+ to describe your general APIs and specify their
+ <a href="http://wiki.netbeans.org/API_Stability#Private">
+ stability categories</a>.
+ If possible please provide simple diagrams.
+ </hint>
+ </question>
+-->
+ <answer id="arch-overall">
+ <p>
+ This is a lexer an syntax highlighting for TextMate grammars. The grammars
+ may be regitered using the system layer.
+ <api name="register-grammar" group="layer" type="export" category="devel" />
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="arch-quality" when="init">
+ How will the <a
href="http://www.netbeans.org/community/guidelines/q-evangelism.html">quality</a>
+ of your code be tested and
+ how are future regressions going to be prevented?
+ <hint>
+ What kind of testing do
+ you want to use? How much functionality, in which areas,
+ should be covered by the tests? How you find out that your
+ project was successful?
+ </hint>
+ </question>
+-->
+ <answer id="arch-quality">
+ <p>
+ Unit tests for the lexer.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="arch-time" when="init">
+ What are the time estimates of the work?
+ <hint>
+ Please express your estimates of how long the design,
implementation,
+ stabilization are likely to last. How many people will be needed to
+ implement this and what is the expected milestone by which the
work should be
+ ready?
+ </hint>
+ </question>
+-->
+ <answer id="arch-time">
+ <p>
+ Unclear.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="arch-usecases" when="init">
+ <hint>
+ Content of this answer will be displayed as part of page at
+ http://www.netbeans.org/download/dev/javadoc/usecases.html
+ You can use tags <usecase name="name> regular html
description </usecase>
+ and if you want to use an URL you can prefix if with @TOP@ to
begin
+ at the root of your javadoc
+ </hint>
+
+ Describe the main <a
href="http://wiki.netbeans.org/API_Design#The_Importance_of_Being_Use_Case_Oriented">
+ use cases</a> of the new API. Who will use it under
+ what circumstances? What kind of code would typically need to be
written
+ to use the module?
+ </question>
+-->
+ <answer id="arch-usecases">
+ <p>
+ <usecase id="register-grammar" name="Register grammar">
+ To register a new TextMate grammar, add it as a file into the system
filesystem,
+ under "Editors/<mime-type>/", and make sure it has an
attribute "textmate-grammar",</mime-type>,
+ whose value is a string representing the TextMate top-level scope.
For example:
+ <pre>
+ <folder name="Editors">
+ <folder name="text">
+ <folder name="x-kotlin">
+ <file name="Kotlin.tmLanguage.json"
url="Kotlin.tmLanguage.json">
+ <attr name="textmate-grammar"
stringvalue="source.kotlin" />
+ </file>
+ </folder>
+ </folder>
+ </folder>
+ </pre>
+ </usecase>
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="arch-what" when="init">
+ What is this project good for?
+ <hint>
+ Please provide here a few lines describing the project,
+ what problem it should solve, provide links to documentation,
+ specifications, etc.
+ </hint>
+ </question>
+-->
+ <answer id="arch-what">
+ <p>
+ This project to allows to easily add syntax highlighting for languages by
+ using the TextMate grammar files.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="arch-where" when="impl">
+ Where one can find sources for your module?
+ <hint>
+ Please provide link to the Hg web client at
+ http://hg.netbeans.org/
+ or just use tag defaultanswer generate='here'
+ </hint>
+ </question>
+-->
+ <answer id="arch-where">
+ <defaultanswer generate='here' />
+ </answer>
+
+
+
+<!--
+ <question id="compat-deprecation" when="init">
+ How the introduction of your project influences functionality
+ provided by previous version of the product?
+ <hint>
+ If you are planning to deprecate/remove/change any existing APIs,
+ list them here accompanied with the reason explaining why you
+ are doing so.
+ </hint>
+ </question>
+-->
+ <answer id="compat-deprecation">
+ <p>
+ No particular plan to deprecate stuff.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="compat-i18n" when="impl">
+ Is your module correctly internationalized?
+ <hint>
+ Correct internationalization means that it obeys instructions
+ at <a
href="http://www.netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/i18n-branding.html">
+ NetBeans I18N pages</a>.
+ </hint>
+ </question>
+-->
+ <answer id="compat-i18n">
+ <p>
+ Yes.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="compat-standards" when="init">
+ Does the module implement or define any standards? Is the
+ implementation exact or does it deviate somehow?
+ </question>
+-->
+ <answer id="compat-standards">
+ <p>
+ Supports the TextMate grammar standard by use of an external library.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="compat-version" when="impl">
+ Can your module coexist with earlier and future
+ versions of itself? Can you correctly read all old settings? Will
future
+ versions be able to read your current settings? Can you read
+ or politely ignore settings stored by a future version?
+
+ <hint>
+ Very helpful for reading settings is to store version number
+ there, so future versions can decide whether how to read/convert
+ the settings and older versions can ignore the new ones.
+ </hint>
+ </question>
+-->
+ <answer id="compat-version">
+ <p>
+ No settings created or read by this module.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="dep-jre" when="final">
+ Which version of JRE do you need (1.2, 1.3, 1.4, etc.)?
+ <hint>
+ It is expected that if your module runs on 1.x that it will run
+ on 1.x+1 if no, state that please. Also describe here cases where
+ you run different code on different versions of JRE and why.
+ </hint>
+ </question>
+-->
+ <answer id="dep-jre">
+ <p>
+ JRE 8.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="dep-jrejdk" when="final">
+ Do you require the JDK or is the JRE enough?
+ </question>
+-->
+ <answer id="dep-jrejdk">
+ <p>
+ JRE.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="dep-nb" when="init">
+ What other NetBeans projects and modules does this one depend on?
+ <hint>
+ Depending on other NetBeans projects influnces the ability of
+ users of your work to customize their own branded version of
+ NetBeans by enabling and disabling some modules. Too
+ much dependencies restrict this kind of customization. If that
+ is your case, then you may want to split your functionality into
+ pieces of autoload, eager and regular modules which can be
+ enabled independently. Usually the answer to this question
+ is generated from your <code>project.xml</code> file, but
+ if it is not guessed correctly, you can suppress it by
+ specifying <defaultanswer generate="none"/> and
+ write here your own. Please describe such projects as imported
APIs using
+ the <code><api name="identification" type="import or export"
category="stable" url="where is the description" /></code>.
+ By doing this information gets listed in the summary page of your
+ javadoc.
+ </hint>
+ </question>
+-->
+ <answer id="dep-nb">
+ <defaultanswer generate='here' />
+ </answer>
+
+
+
+<!--
+ <question id="dep-non-nb" when="init">
+ What other projects outside NetBeans does this one depend on?
+
+ <hint>
+ Depending on 3rd party libraries is always problematic,
+ especially if they are not open source, as that complicates
+ the licensing scheme of NetBeans. Please enumerate your
+ external dependencies here, so it is correctly understood since
+ the begining what are the legal implications of your project.
+ Also please note that
+ some non-NetBeans projects are packaged as NetBeans modules
+ (see <a href="http://libs.netbeans.org/">libraries</a>) and
+ it is preferred to use this approach when more modules may
+ depend and share such third-party libraries.
+ </hint>
+ </question>
+-->
+ <answer id="dep-non-nb">
+ <p>
+ This project uses the TextMate support for Eclipse.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="dep-platform" when="init">
+ On which platforms does your module run? Does it run in the same
+ way on each?
+ <hint>
+ If you plan any dependency on OS or any usage of native code,
+ please describe why you are doing so and describe how you envision
+ to enforce the portability of your code.
+ Please note that there is a support for <a
href="http://www.netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/api.html#how-os-specific">OS
conditionally
+ enabled modules</a> which together with autoload/eager modules
+ can allow you to enable to provide the best OS aware support
+ on certain OSes while providing compatibility bridge on the not
+ supported ones.
+ Also please list the supported
+ OSes/HW platforms and mentioned the lovest version of JDK required
+ for your project to run on. Also state whether JRE is enough or
+ you really need JDK.
+ </hint>
+ </question>
+-->
+ <answer id="dep-platform">
+ <p>
+ Any platform.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="deploy-dependencies" when="final">
+ What do other modules need to do to declare a dependency on this
one,
+ in addition to or instead of the normal module dependency
declaration
+ (e.g. tokens to require)?
+ <hint>
+ Provide a sample of the actual lines you would add to a module
manifest
+ to declare a dependency, for example OpenIDE-Module-Requires:
some.token.
+ If other modules should not depend on this module, or should
just use a
+ simple regular module dependency, you can just answer
"nothing". If you
+ intentionally expose a semistable API to clients using
implementation
+ dependencies, you should mention that here (but there is no
need to give
+ an example of usage).
+ </hint>
+ </question>
+-->
+ <answer id="deploy-dependencies">
+ <p>
+ No real dependencies needed currently.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="deploy-jar" when="impl">
+ Do you deploy just module JAR file(s) or other files as well?
+ <hint>
+ Usually a module consist of one JAR file (perhaps with Class-Path
+ extensions) and also a configuration file that enables it. If you
+ have any other files, use
+ <api group="java.io.File" name="yourname" type="export"
category="friend">...</api>
+ to define the location, name and stability of your files (of course
+ changing "yourname" and "friend" to suit your needs).
+
+ If it uses more than one JAR, describe where they are located, how
+ they refer to each other.
+ If it consist of module JAR(s) and other files, please describe
+ what is their purpose, why other files are necessary. Please
+ make sure that installation/uninstallation leaves the system
+ in state as it was before installation.
+ </hint>
+ </question>
+-->
+ <answer id="deploy-jar">
+ <p>
+ Uses the core jar from TextMate for Eclipse.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="deploy-nbm" when="impl">
+ Can you deploy an NBM via the Update Center?
+ <hint>
+ If not why?
+ </hint>
+ </question>
+-->
+ <answer id="deploy-nbm">
+ <p>
+ Yes.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="deploy-packages" when="init">
+ Are packages of your module made inaccessible by not declaring them
+ public?
+
+ <hint>
+ By default NetBeans build harness treats all packages are private.
+ If you export some of them - either as public or friend packages,
+ you should have a reason. If the reason is described elsewhere
+ in this document, you can ignore this question.
+ </hint>
+ </question>
+-->
+ <answer id="deploy-packages">
+ <p>
+ Yes.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="deploy-shared" when="final">
+ Do you need to be installed in the shared location only, or in the
user directory only,
+ or can your module be installed anywhere?
+ <hint>
+ Installation location shall not matter, if it does explain why.
+ Consider also whether <code>InstalledFileLocator</code> can help.
+ </hint>
+ </question>
+-->
+ <answer id="deploy-shared">
+ <p>
+ Anywhere.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="exec-ant-tasks" when="impl">
+ Do you define or register any ant tasks that other can use?
+
+ <hint>
+ If you provide an ant task that users can use, you need to be very
+ careful about its syntax and behaviour, as it most likely forms an
+ API for end users and as there is a lot of end users, their
reaction
+ when such API gets broken can be pretty strong.
+ </hint>
+ </question>
+-->
+ <answer id="exec-ant-tasks">
+ <p>
+ No.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="exec-classloader" when="impl">
+ Does your code create its own class loader(s)?
+ <hint>
+ A bit unusual. Please explain why and what for.
+ </hint>
+ </question>
+-->
+ <answer id="exec-classloader">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="exec-component" when="impl">
+ Is execution of your code influenced by any (string) property
+ of any of your components?
+
+ <hint>
+ Often <code>JComponent.getClientProperty</code>,
<code>Action.getValue</code>
+ or <code>PropertyDescriptor.getValue</code>, etc. are used to
influence
+ a behavior of some code. This of course forms an interface that
should
+ be documented. Also if one depends on some interface that an object
+ implements (<code>component instanceof Runnable</code>) that forms
an
+ API as well.
+ </hint>
+ </question>
+-->
+ <answer id="exec-component">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="exec-introspection" when="impl">
+ Does your module use any kind of runtime type information
(<code>instanceof</code>,
+ work with <code>java.lang.Class</code>, etc.)?
+ <hint>
+ Check for cases when you have an object of type A and you also
+ expect it to (possibly) be of type B and do some special action.
That
+ should be documented. The same applies on operations in meta-level
+ (Class.isInstance(...), Class.isAssignableFrom(...), etc.).
+ </hint>
+ </question>
+-->
+ <answer id="exec-introspection">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="exec-privateaccess" when="final">
+ Are you aware of any other parts of the system calling some of
+ your methods by reflection?
+ <hint>
+ If so, describe the "contract" as an API. Likely private or friend
one, but
+ still API and consider rewrite of it.
+ </hint>
+ </question>
+-->
+ <answer id="exec-privateaccess">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="exec-process" when="impl">
+ Do you execute an external process from your module? How do you
ensure
+ that the result is the same on different platforms? Do you parse
output?
+ Do you depend on result code?
+ <hint>
+ If you feed an input, parse the output please declare that as an
API.
+ </hint>
+ </question>
+-->
+ <answer id="exec-process">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="exec-property" when="impl">
+ Is execution of your code influenced by any environment or
+ Java system (<code>System.getProperty</code>) property?
+ On a similar note, is there something interesting that you
+ pass to <code>java.util.logging.Logger</code>? Or do you observe
+ what others log?
+ <hint>
+ If there is a property that can change the behavior of your
+ code, somebody will likely use it. You should describe what it
does
+ and the <a href="http://wiki.netbeans.org/API_Stability">stability
category</a>
+ of this API. You may use
+ <pre>
+ <api type="export" group="property" name="id"
category="private" url="http://...">
+ description of the property, where it is used, what it
influence, etc.
+ </api>
+ </pre>
+ </hint>
+ </question>
+-->
+ <answer id="exec-property">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="exec-reflection" when="impl">
+ Does your code use Java Reflection to execute other code?
+ <hint>
+ This usually indicates a missing or insufficient API in the other
+ part of the system. If the other side is not aware of your
dependency
+ this contract can be easily broken.
+ </hint>
+ </question>
+-->
+ <answer id="exec-reflection">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="exec-threading" when="init">
+ What threading models, if any, does your module adhere to? How the
+ project behaves with respect to threading?
+ <hint>
+ Is your API threadsafe? Can it be accessed from any threads or
+ just from some dedicated ones? Any special relation to AWT and
+ its Event Dispatch thread? Also
+ if your module calls foreign APIs which have a specific
threading model,
+ indicate how you comply with the requirements for
multithreaded access
+ (synchronization, mutexes, etc.) applicable to those APIs.
+ If your module defines any APIs, or has complex internal
structures
+ that might be used from multiple threads, declare how you
protect
+ data against concurrent access, race conditions, deadlocks,
etc.,
+ and whether such rules are enforced by runtime warnings,
errors, assertions, etc.
+ Examples: a class might be non-thread-safe (like Java
Collections); might
+ be fully thread-safe (internal locking); might require access
through a mutex
+ (and may or may not automatically acquire that mutex on behalf
of a client method);
+ might be able to run only in the event queue; etc.
+ Also describe when any events are fired: synchronously,
asynchronously, etc.
+ Ideas: <a
href="http://core.netbeans.org/proposals/threading/index.html#recommendations">Threading
Recommendations</a> (in progress)
+ </hint>
+ </question>
+-->
+ <answer id="exec-threading">
+ <p>
+ The threading model is inherited from the lexing infrastructure.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="format-clipboard" when="impl">
+ Which data flavors (if any) does your code read from or insert to
+ the clipboard (by access to clipboard on means calling methods on
<code>java.awt.datatransfer.Transferable</code>?
+
+ <hint>
+ Often Node's deal with clipboard by usage of
<code>Node.clipboardCopy, Node.clipboardCut and Node.pasteTypes</code>.
+ Check your code for overriding these methods.
+ </hint>
+ </question>
+-->
+ <answer id="format-clipboard">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="format-dnd" when="impl">
+ Which protocols (if any) does your code understand during Drag
& Drop?
+ <hint>
+ Often Node's deal with clipboard by usage of <code>Node.drag,
Node.getDropType</code>.
+ Check your code for overriding these methods. Btw. if they are not
overridden, they
+ by default delegate to <code>Node.clipboardCopy, Node.clipboardCut
and Node.pasteTypes</code>.
+ </hint>
+ </question>
+-->
+ <answer id="format-dnd">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="format-types" when="impl">
+ Which protocols and file formats (if any) does your module read or
write on disk,
+ or transmit or receive over the network? Do you generate an ant
build script?
+ Can it be edited and modified?
+
+ <hint>
+ <p>
+ Files can be read and written by other programs, modules and
users. If they influence
+ your behaviour, make sure you either document the format or claim
that it is a private
+ api (using the <api> tag).
+ </p>
+
+ <p>
+ If you generate an ant build file, this is very likely going to be
seen by end users and
+ they will be attempted to edit it. You should be ready for that
and provide here a link
+ to documentation that you have for such purposes and also describe
how you are going to
+ understand such files during next release, when you (very likely)
slightly change the
+ format.
+ </p>
+ </hint>
+ </question>
+-->
+ <answer id="format-types">
+ <p>
+ The TextMate grammar files are read by the TextMate support for Eclipse
library.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="lookup-lookup" when="init">
+ Does your module use <code>org.openide.util.Lookup</code>
+ or any similar technology to find any components to communicate
with? Which ones?
+
+ <hint>
+ NetBeans is build around a generic registry of services called
+ lookup. It is preferable to use it for registration and discovery
+ if possible. See
+ <a
href="http://www.netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/lookup/doc-files/index.html">
+ The Solution to Comunication Between Components
+ </a>. If you do not plan to use lookup and insist usage
+ of other solution, then please describe why it is not working for
+ you.
+ <br/>
+ When filling the final version of your arch document, please
+ describe the interfaces you are searching for, where
+ are defined, whether you are searching for just one or more of
them,
+ if the order is important, etc. Also classify the stability of such
+ API contract. Use <api group=&lookup& /> tag, so
+ your information gets listed in the summary page of your javadoc.
+ </hint>
+ </question>
+-->
+ <answer id="lookup-lookup">
+ <p>
+ Grammar files are looked up on the system filesystem.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="lookup-register" when="final">
+ Do you register anything into lookup for other code to find?
+ <hint>
+ Do you register using layer file or using a declarative annotation
such as <code>@ServiceProvider</code>?
+ Who is supposed to find your component?
+ </hint>
+ </question>
+-->
+ <answer id="lookup-register">
+ <p>
+ Languages are dynamically added into the MimeLookup.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="lookup-remove" when="final">
+ Do you remove entries of other modules from lookup?
+ <hint>
+ Why? Of course, that is possible, but it can be dangerous. Is the
module
+ your are masking resource from aware of what you are doing?
+ </hint>
+ </question>
+-->
+ <answer id="lookup-remove">
+ <p>
+ No.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="perf-exit" when="final">
+ Does your module run any code on exit?
+ </question>
+-->
+ <answer id="perf-exit">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="perf-huge_dialogs" when="final">
+ Does your module contain any dialogs or wizards with a large
number of
+ GUI controls such as combo boxes, lists, trees, or text areas?
+ </question>
+-->
+ <answer id="perf-huge_dialogs">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="perf-limit" when="init">
+ Are there any hard-coded or practical limits in the number or size
of
+ elements your code can handle?
+ <hint>
+ Most of algorithms have increasing memory and speed complexity
+ with respect to size of data they operate on. What is the
critical
+ part of your project that can be seen as a bottleneck with
+ respect to speed or required memory? What are the practical
+ sizes of data you tested your project with? What is your
estimate
+ of potential size of data that would cause visible performance
+ problems? Is there some kind of check to detect such situation
+ and prevent "hard" crashes - for example the
CloneableEditorSupport
+ checks for size of a file to be opened in editor
+ and if it is larger than 1Mb it shows a dialog giving the
+ user the right to decide - e.g. to cancel or commit suicide.
+ </hint>
+ </question>
+-->
+ <answer id="perf-limit">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="perf-mem" when="final">
+ How much memory does your component consume? Estimate
+ with a relation to the number of windows, etc.
+ </question>
+-->
+ <answer id="perf-mem">
+ <p>
+ Not known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="perf-menus" when="final">
+ Does your module use dynamically updated context menus, or
+ context-sensitive actions with complicated and slow enablement
logic?
+ <hint>
+ If you do a lot of tricks when adding actions to regular or
context menus, you can significantly
+ slow down display of the menu, even when the user is not using
your action. Pay attention to
+ actions you add to the main menu bar, and to context menus of
foreign nodes or components. If
+ the action is conditionally enabled, or changes its display
dynamically, you need to check the
+ impact on performance. In some cases it may be more
appropriate to make a simple action that is
+ always enabled but does more detailed checks in a dialog if it
is actually run.
+ </hint>
+ </question>
+-->
+ <answer id="perf-menus">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="perf-progress" when="final">
+ Does your module execute any long-running tasks?
+
+ <hint>Long running tasks should never block
+ AWT thread as it badly hurts the UI
+ <a
href="http://performance.netbeans.org/responsiveness/issues.html">
+ responsiveness</a>.
+ Tasks like connecting over
+ network, computing huge amount of data, compilation
+ be done asynchronously (for example
+ using <code>RequestProcessor</code>), definitively it should
+ not block AWT thread.
+ </hint>
+ </question>
+-->
+ <answer id="perf-progress">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="perf-scale" when="init">
+ Which external criteria influence the performance of your
+ program (size of file in editor, number of files in menu,
+ in source directory, etc.) and how well your code scales?
+ <hint>
+ Please include some estimates, there are other more detailed
+ questions to answer in later phases of implementation.
+ </hint>
+ </question>
+-->
+ <answer id="perf-scale">
+ <p>
+ The size of the grammar files and the size of the edited file affect the
performance.
+ Due to the format of the TextMate grammars, long lines may negativelly
affect performance.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="perf-spi" when="init">
+ How the performance of the plugged in code will be enforced?
+ <hint>
+ If you allow foreign code to be plugged into your own module, how
+ do you enforce that it will behave correctly and quickly and will
not
+ negatively influence the performance of your own module?
+ </hint>
+ </question>
+-->
+ <answer id="perf-spi">
+ <p>
+ Not enforced.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="perf-startup" when="final">
+ Does your module run any code on startup?
+ </question>
+-->
+ <answer id="perf-startup">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="perf-wakeup" when="final">
+ Does any piece of your code wake up periodically and do something
+ even when the system is otherwise idle (no user interaction)?
+ </question>
+-->
+ <answer id="perf-wakeup">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="resources-file" when="final">
+ Does your module use <code>java.io.File</code> directly?
+
+ <hint>
+ NetBeans provide a logical wrapper over plain files called
+ <code>org.openide.filesystems.FileObject</code> that
+ provides uniform access to such resources and is the preferred
+ way that should be used. But of course there can be situations when
+ this is not suitable.
+ </hint>
+ </question>
+-->
+ <answer id="resources-file">
+ <p>
+ The TextMate support for Eclipse is using Files directly.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="resources-layer" when="final">
+ Does your module provide own layer? Does it create any files or
+ folders in it? What it is trying to communicate by that and with
which
+ components?
+
+ <hint>
+ NetBeans allows automatic and declarative installation of
resources
+ by module layers. Module register files into appropriate places
+ and other components use that information to perform their task
+ (build menu, toolbar, window layout, list of templates, set of
+ options, etc.).
+ </hint>
+ </question>
+-->
+ <answer id="resources-layer">
+ <p>
+ Fonts&Colors are registered in the layer.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="resources-mask" when="final">
+ Does your module mask/hide/override any resources provided by
other modules in
+ their layers?
+
+ <hint>
+ If you mask a file provided by another module, you probably depend
+ on that and do not want the other module to (for example) change
+ the file's name. That module shall thus make that file available
as an API
+ of some stability category.
+ </hint>
+ </question>
+-->
+ <answer id="resources-mask">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="resources-preferences" when="final">
+ Does your module uses preferences via Preferences API? Does your
module use NbPreferences or
+ or regular JDK Preferences ? Does it read, write or both ?
+ Does it share preferences with other modules ? If so, then why ?
+ <hint>
+ You may use
+ <api type="export" group="preferences"
+ name="preference node name" category="private">
+ description of individual keys, where it is used, what it
+ influences, whether the module reads/write it, etc.
+ </api>
+ Due to XML ID restrictions, rather than
/org/netbeans/modules/foo give the "name" as org.netbeans.modules.foo.
+ Note that if you use NbPreferences this name will then be the
same as the code name base of the module.
+ </hint>
+ </question>
+-->
+ <answer id="resources-preferences">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="resources-read" when="final">
+ Does your module read any resources from layers? For what purpose?
+
+ <hint>
+ As this is some kind of intermodule dependency, it is a kind of
API.
+ Please describe it and classify according to
+ <a href="http://wiki.netbeans.org/API_Design#What_is_an_API.3F">
+ common stability categories</a>.
+ </hint>
+ </question>
+-->
+ <answer id="resources-read">
+ <p>
+ The grammar files are read from the system filesystem.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="security-grant" when="final">
+ Does your code grant additional rights to some other code?
+ <hint>Avoid using a class loader that adds extra
+ permissions to loaded code unless really necessary.
+ Also note that your API implementation
+ can also expose unneeded permissions to enemy code by
+ calling AccessController.doPrivileged().</hint>
+ </question>
+-->
+ <answer id="security-grant">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+
+
+<!--
+ <question id="security-policy" when="final">
+ Does your functionality require modifications to the standard
policy file?
+ <hint>Your code might pass control to third-party code not
+ coming from trusted domains. This could be code downloaded over the
+ network or code coming from libraries that are not bundled
+ with NetBeans. Which permissions need to be granted to which
domains?</hint>
+ </question>
+-->
+ <answer id="security-policy">
+ <p>
+ None known.
+ </p>
+ </answer>
+
+</api-answers>
diff --git a/ide/textmate.lexer/build.xml b/ide/textmate.lexer/build.xml
new file mode 100644
index 0000000..d563ec0
--- /dev/null
+++ b/ide/textmate.lexer/build.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+-->
+<project basedir="." default="netbeans" name="ide/textmate.lexer">
+ <description>Builds, tests, and runs the project
org.netbeans.modules.textmate.lexer</description>
+ <import file="../../nbbuild/templates/projectized.xml"/>
+</project>
diff --git a/ide/textmate.lexer/external/binaries-list
b/ide/textmate.lexer/external/binaries-list
new file mode 100644
index 0000000..8e77a43
--- /dev/null
+++ b/ide/textmate.lexer/external/binaries-list
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+7CDFC30451010E4D6C65AF5A3A4F357563289245 org.jruby.jcodings:jcodings:1.0.41
+655CC3ABA1BC9DBDD653F28937BEC16F3E9C4CEC org.jruby.joni:joni:2.1.11
+041CFB536DA85BCB9DBDF2E465BC952D40704863
org.eclipse.tm4e.core_0.2.0.201809031154.jar
diff --git a/ide/textmate.lexer/external/jcodings-1.0.41-license.txt
b/ide/textmate.lexer/external/jcodings-1.0.41-license.txt
new file mode 100644
index 0000000..3bec304
--- /dev/null
+++ b/ide/textmate.lexer/external/jcodings-1.0.41-license.txt
@@ -0,0 +1,23 @@
+Name: jcodings
+Version: 1.0.41
+License: MIT-nocopyright
+Description: Needed by TextMate support for Eclipse
+Origin: https://github.com/jruby/jcodings
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/ide/textmate.lexer/external/joni-2.1.11-license.txt
b/ide/textmate.lexer/external/joni-2.1.11-license.txt
new file mode 100644
index 0000000..0ab411d
--- /dev/null
+++ b/ide/textmate.lexer/external/joni-2.1.11-license.txt
@@ -0,0 +1,27 @@
+Name: jcodings
+Version: 2.1.11
+License: MIT-jruby
+Description: Needed by TextMate support for Eclipse
+Origin: https://github.com/jruby/joni
+
+MIT License
+
+Copyright (c) 2017 JRuby Team
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git
a/ide/textmate.lexer/external/org.eclipse.tm4e.core_0.2.0.201809031154-license.txt
b/ide/textmate.lexer/external/org.eclipse.tm4e.core_0.2.0.201809031154-license.txt
new file mode 100644
index 0000000..9274432
--- /dev/null
+++
b/ide/textmate.lexer/external/org.eclipse.tm4e.core_0.2.0.201809031154-license.txt
@@ -0,0 +1,209 @@
+Name: TextMate support for Eclipse
+Version: 0.2.0.201809031154
+License: EPL-v10
+Description: Used to interpret TextMate grammars
+Origin: https://github.com/eclipse/tm4e
+
+Eclipse Public License - v 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
+CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial code and documentation
+ distributed under this Agreement, and
+b) in the case of each subsequent Contributor:
+ i) changes to the Program, and
+ ii) additions to the Program;
+
+ where such changes and/or additions to the Program originate from and are
+ distributed by that particular Contributor. A Contribution 'originates'
+ from a Contributor if it was added to the Program by such Contributor
+ itself or anyone acting on such Contributor's behalf. Contributions do not
+ include additions to the Program which: (i) are separate modules of
+ software distributed in conjunction with the Program under their own
+ license agreement, and (ii) are not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program.
+
+"Licensed Patents" mean patent claims licensable by a Contributor which are
+necessarily infringed by the use or sale of its Contribution alone or when
+combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this
+Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement,
+including all Contributors.
+
+2. GRANT OF RIGHTS
+ a) Subject to the terms of this Agreement, each Contributor hereby grants
+ Recipient a non-exclusive, worldwide, royalty-free copyright license to
+ reproduce, prepare derivative works of, publicly display, publicly
+ perform, distribute and sublicense the Contribution of such Contributor,
+ if any, and such derivative works, in source code and object code form.
+ b) Subject to the terms of this Agreement, each Contributor hereby grants
+ Recipient a non-exclusive, worldwide, royalty-free patent license under
+ Licensed Patents to make, use, sell, offer to sell, import and otherwise
+ transfer the Contribution of such Contributor, if any, in source code and
+ object code form. This patent license shall apply to the combination of
+ the Contribution and the Program if, at the time the Contribution is
+ added by the Contributor, such addition of the Contribution causes such
+ combination to be covered by the Licensed Patents. The patent license
+ shall not apply to any other combinations which include the Contribution.
+ No hardware per se is licensed hereunder.
+ c) Recipient understands that although each Contributor grants the licenses
+ to its Contributions set forth herein, no assurances are provided by any
+ Contributor that the Program does not infringe the patent or other
+ intellectual property rights of any other entity. Each Contributor
+ disclaims any liability to Recipient for claims brought by any other
+ entity based on infringement of intellectual property rights or
+ otherwise. As a condition to exercising the rights and licenses granted
+ hereunder, each Recipient hereby assumes sole responsibility to secure
+ any other intellectual property rights needed, if any. For example, if a
+ third party patent license is required to allow Recipient to distribute
+ the Program, it is Recipient's responsibility to acquire that license
+ before distributing the Program.
+ d) Each Contributor represents that to its knowledge it has sufficient
+ copyright rights in its Contribution, if any, to grant the copyright
+ license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under
+its own license agreement, provided that:
+
+ a) it complies with the terms and conditions of this Agreement; and
+ b) its license agreement:
+ i) effectively disclaims on behalf of all Contributors all warranties
+ and conditions, express and implied, including warranties or
+ conditions of title and non-infringement, and implied warranties or
+ conditions of merchantability and fitness for a particular purpose;
+ ii) effectively excludes on behalf of all Contributors all liability for
+ damages, including direct, indirect, special, incidental and
+ consequential damages, such as lost profits;
+ iii) states that any provisions which differ from this Agreement are
+ offered by that Contributor alone and not by any other party; and
+ iv) states that source code for the Program is available from such
+ Contributor, and informs licensees how to obtain it in a reasonable
+ manner on or through a medium customarily used for software exchange.
+
+When the Program is made available in source code form:
+
+ a) it must be made available under this Agreement; and
+ b) a copy of this Agreement must be included with each copy of the Program.
+ Contributors may not remove or alter any copyright notices contained
+ within the Program.
+
+Each Contributor must identify itself as the originator of its Contribution,
+if
+any, in a manner that reasonably allows subsequent Recipients to identify the
+originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities with
+respect to end users, business partners and the like. While this license is
+intended to facilitate the commercial use of the Program, the Contributor who
+includes the Program in a commercial product offering should do so in a manner
+which does not create potential liability for other Contributors. Therefore,
+if a Contributor includes the Program in a commercial product offering, such
+Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
+every other Contributor ("Indemnified Contributor") against any losses,
+damages and costs (collectively "Losses") arising from claims, lawsuits and
+other legal actions brought by a third party against the Indemnified
+Contributor to the extent caused by the acts or omissions of such Commercial
+Contributor in connection with its distribution of the Program in a commercial
+product offering. The obligations in this section do not apply to any claims
+or Losses relating to any actual or alleged intellectual property
+infringement. In order to qualify, an Indemnified Contributor must:
+a) promptly notify the Commercial Contributor in writing of such claim, and
+b) allow the Commercial Contributor to control, and cooperate with the
+Commercial Contributor in, the defense and any related settlement
+negotiations. The Indemnified Contributor may participate in any such claim at
+its own expense.
+
+For example, a Contributor might include the Program in a commercial product
+offering, Product X. That Contributor is then a Commercial Contributor. If
+that Commercial Contributor then makes performance claims, or offers
+warranties related to Product X, those performance claims and warranties are
+such Commercial Contributor's responsibility alone. Under this section, the
+Commercial Contributor would have to defend claims against the other
+Contributors related to those performance claims and warranties, and if a
+court requires any other Contributor to pay any damages as a result, the
+Commercial Contributor must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
+Recipient is solely responsible for determining the appropriateness of using
+and distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement , including but not limited to the
+risks and costs of program errors, compliance with applicable laws, damage to
+or loss of data, programs or equipment, and unavailability or interruption of
+operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
+CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
+LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
+EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
+OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of the
+remainder of the terms of this Agreement, and without further action by the
+parties hereto, such provision shall be reformed to the minimum extent
+necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Program itself
+(excluding combinations of the Program with other software or hardware)
+infringes such Recipient's patent(s), then such Recipient's rights granted
+under Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to
+comply with any of the material terms or conditions of this Agreement and does
+not cure such failure in a reasonable period of time after becoming aware of
+such noncompliance. If all Recipient's rights under this Agreement terminate,
+Recipient agrees to cease use and distribution of the Program as soon as
+reasonably practicable. However, Recipient's obligations under this Agreement
+and any licenses granted by Recipient relating to the Program shall continue
+and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in
+order to avoid inconsistency the Agreement is copyrighted and may only be
+modified in the following manner. The Agreement Steward reserves the right to
+publish new versions (including revisions) of this Agreement from time to
+time. No one other than the Agreement Steward has the right to modify this
+Agreement. The Eclipse Foundation is the initial Agreement Steward. The
+Eclipse Foundation may assign the responsibility to serve as the Agreement
+Steward to a suitable separate entity. Each new version of the Agreement will
+be given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new version of the
+Agreement is published, Contributor may elect to distribute the Program
+(including its Contributions) under the new version. Except as expressly
+stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
+licenses to the intellectual property of any Contributor under this Agreement,
+whether expressly, by implication, estoppel or otherwise. All rights in the
+Program not expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and the
+intellectual property laws of the United States of America. No party to this
+Agreement will bring a legal action under this Agreement more than one year
+after the cause of action arose. Each party waives its rights to a jury trial
in
+any resulting litigation.
diff --git a/ide/textmate.lexer/manifest.mf b/ide/textmate.lexer/manifest.mf
new file mode 100644
index 0000000..9c0eeb0
--- /dev/null
+++ b/ide/textmate.lexer/manifest.mf
@@ -0,0 +1,7 @@
+Manifest-Version: 1.0
+AutoUpdate-Show-In-Client: false
+OpenIDE-Module: org.netbeans.modules.textmate.lexer/0
+OpenIDE-Module-Layer: org/netbeans/modules/textmate/lexer/resources/layer.xml
+OpenIDE-Module-Localizing-Bundle:
org/netbeans/modules/textmate/lexer/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
diff --git a/ide/textmate.lexer/nbproject/project.properties
b/ide/textmate.lexer/nbproject/project.properties
new file mode 100644
index 0000000..3576ad1
--- /dev/null
+++ b/ide/textmate.lexer/nbproject/project.properties
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+is.autoload=true
+javac.source=1.8
+javac.compilerargs=-Xlint -Xlint:-serial
+javadoc.arch=${basedir}/arch.xml
+release.external/joni-2.1.11.jar=modules/ext/joni-2.1.11.jar
+release.external/jcodings-1.0.41.jar=modules/ext/jcodings-1.0.41.jar
+release.external/org.eclipse.tm4e.core_0.2.0.201809031154.jar=modules/ext/org.eclipse.tm4e.core_0.2.0.201809031154.jar
diff --git a/ide/textmate.lexer/nbproject/project.xml
b/ide/textmate.lexer/nbproject/project.xml
new file mode 100644
index 0000000..cac8085
--- /dev/null
+++ b/ide/textmate.lexer/nbproject/project.xml
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+ <type>org.netbeans.modules.apisupport.project</type>
+ <configuration>
+ <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+
<code-name-base>org.netbeans.modules.textmate.lexer</code-name-base>
+ <module-dependencies>
+ <dependency>
+ <code-name-base>com.google.gson</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>2.7.0</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.netbeans.api.templates</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>1.12</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+
<code-name-base>org.netbeans.modules.editor.lib2</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <release-version>1</release-version>
+ <specification-version>2.22</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+
<code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <release-version>1</release-version>
+ <specification-version>1.44</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+
<code-name-base>org.netbeans.modules.editor.settings</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <release-version>1</release-version>
+ <specification-version>1.61</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+
<code-name-base>org.netbeans.modules.editor.util</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <release-version>1</release-version>
+ <specification-version>1.69</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.netbeans.modules.lexer</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <release-version>2</release-version>
+ <specification-version>1.67.0.1</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.awt</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>7.72</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.dialogs</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>7.46</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.filesystems</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>9.14</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.loaders</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>7.71</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.nodes</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>7.49</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.text</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>6.71</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.util</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>9.11</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.util.lookup</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>8.37</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.util.ui</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>9.12</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.windows</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>6.80</specification-version>
+ </run-dependency>
+ </dependency>
+ </module-dependencies>
+ <test-dependencies>
+ <test-type>
+ <name>unit</name>
+ <test-dependency>
+
<code-name-base>org.netbeans.libs.junit4</code-name-base>
+ <compile-dependency/>
+ </test-dependency>
+ <test-dependency>
+
<code-name-base>org.netbeans.modules.lexer</code-name-base>
+ <compile-dependency/>
+ <test/>
+ </test-dependency>
+ <test-dependency>
+
<code-name-base>org.netbeans.modules.nbjunit</code-name-base>
+ <recursive/>
+ <compile-dependency/>
+ </test-dependency>
+ </test-type>
+ </test-dependencies>
+ <public-packages/>
+ <class-path-extension>
+
<runtime-relative-path>ext/joni-2.1.11.jar</runtime-relative-path>
+ <binary-origin>external/joni-2.1.11.jar</binary-origin>
+ </class-path-extension>
+ <class-path-extension>
+
<runtime-relative-path>ext/jcodings-1.0.41.jar</runtime-relative-path>
+ <binary-origin>external/jcodings-1.0.41.jar</binary-origin>
+ </class-path-extension>
+ <class-path-extension>
+
<runtime-relative-path>ext/org.eclipse.tm4e.core_0.2.0.201809031154.jar</runtime-relative-path>
+
<binary-origin>external/org.eclipse.tm4e.core_0.2.0.201809031154.jar</binary-origin>
+ </class-path-extension>
+ </data>
+ </configuration>
+</project>
diff --git
a/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/Bundle.properties
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/Bundle.properties
new file mode 100644
index 0000000..33d008c
--- /dev/null
+++
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/Bundle.properties
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+OpenIDE-Module-Name=TextMate Lexer
diff --git
a/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/SyntaxHighlighting.java
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/SyntaxHighlighting.java
new file mode 100644
index 0000000..6cdfd9a
--- /dev/null
+++
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/SyntaxHighlighting.java
@@ -0,0 +1,862 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.netbeans.modules.textmate.lexer;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.Document;
+import javax.swing.text.SimpleAttributeSet;
+import org.netbeans.api.editor.mimelookup.MimeLookup;
+import org.netbeans.api.editor.mimelookup.MimePath;
+import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.api.editor.settings.AttributesUtilities;
+import org.netbeans.api.editor.settings.EditorStyleConstants;
+import org.netbeans.api.editor.settings.FontColorSettings;
+import org.netbeans.api.lexer.Language;
+import org.netbeans.api.lexer.LanguagePath;
+import org.netbeans.api.lexer.Token;
+import org.netbeans.api.lexer.TokenHierarchy;
+import org.netbeans.api.lexer.TokenHierarchyEvent;
+import org.netbeans.api.lexer.TokenHierarchyEventType;
+import org.netbeans.api.lexer.TokenHierarchyListener;
+import org.netbeans.api.lexer.TokenId;
+import org.netbeans.api.lexer.TokenSequence;
+import org.netbeans.lib.editor.util.ListenerList;
+import org.netbeans.lib.editor.util.swing.DocumentUtilities;
+import org.netbeans.spi.editor.highlighting.HighlightsLayer;
+import org.netbeans.spi.editor.highlighting.HighlightsLayerFactory;
+import org.netbeans.spi.editor.highlighting.HighlightsSequence;
+import org.netbeans.spi.editor.highlighting.ZOrder;
+import
org.netbeans.spi.editor.highlighting.support.AbstractHighlightsContainer;
+import org.openide.util.Lookup;
+import org.openide.util.LookupEvent;
+import org.openide.util.LookupListener;
+import org.openide.util.WeakListeners;
+
+/**Copied from editor.lib2, converts the tokens to AttributeSet in a way that
+ * works for TextmateToken.
+ * The syntax coloring layer.
+ * <br>
+ * It excludes newline chars from any colorings so that if e.g. a whitespace
highlighting is set
+ * the rest of line after newline is not colored.
+ *
+ * @author Vita Stejskal
+ * @author Miloslav Metelka
+ */
+public final class SyntaxHighlighting extends AbstractHighlightsContainer
+implements TokenHierarchyListener, ChangeListener {
+
+ //
-J-Dorg.netbeans.modules.editor.lib2.highlighting.SyntaxHighlighting.level=FINEST
+ private static final Logger LOG =
Logger.getLogger(SyntaxHighlighting.class.getName());
+
+ public static final String LAYER_TYPE_ID =
"org.netbeans.modules.editor.lib2.highlighting.SyntaxHighlighting"; //NOI18N
+
+ /**
+ * Static cache for colorings mapping mime-path to coloring info.
+ */
+ private static final HashMap<String, FCSInfo<?>> globalFCSCache = new
HashMap<String, FCSInfo<?>>();
+
+ /**
+ * Local cache of items from globalFCSCache.
+ */
+ private final HashMap<String, FCSInfo<?>> fcsCache = new HashMap<String,
FCSInfo<?>>();
+
+ private final Document document;
+
+ /**
+ * Either null or a mime-type that starts with "test" and it's used
+ * for preview in Tools/Options/Fonts-and-Colors.
+ */
+ private final String mimeTypeForOptions;
+
+ private final TokenHierarchy<? extends Document> hierarchy;
+
+ private long version = 0;
+
+ /** Creates a new instance of SyntaxHighlighting */
+ public SyntaxHighlighting(Document document) {
+ this.document = document;
+ String mimeType = (String) document.getProperty("mimeType"); //NOI18N
+ if (mimeType != null && mimeType.startsWith("test")) { //NOI18N
+ this.mimeTypeForOptions = mimeType;
+ } else {
+ this.mimeTypeForOptions = null;
+ }
+
+ // Start listening on changes in global colorings since they may
affect colorings for target language
+ findFCSInfo("", null);
+
+ hierarchy = TokenHierarchy.get(document);
+
hierarchy.addTokenHierarchyListener(WeakListeners.create(TokenHierarchyListener.class,
this, hierarchy));
+ }
+
+ public @Override HighlightsSequence getHighlights(int startOffset, int
endOffset) {
+ long lVersion = getVersion();
+ if (hierarchy.isActive()) {
+ return new HSImpl(lVersion, hierarchy, startOffset, endOffset);
+ } else {
+ return HighlightsSequence.EMPTY;
+ }
+ }
+
+ // ----------------------------------------------------------------------
+ // TokenHierarchyListener implementation
+ // ----------------------------------------------------------------------
+
+ public @Override void tokenHierarchyChanged(TokenHierarchyEvent evt) {
+ if (evt.type() == TokenHierarchyEventType.LANGUAGE_PATHS) {
+ // ignore
+ return;
+ }
+
+ synchronized (this) {
+ version++;
+ }
+
+ if (LOG.isLoggable(Level.FINEST)) {
+ StringBuilder sb = new StringBuilder();
+ TokenSequence<?> ts = hierarchy.tokenSequence();
+
+ sb.append("\n"); //NOI18N
+ sb.append("Tokens after change:
<").append(evt.affectedStartOffset()).append(",
").append(evt.affectedEndOffset()).append(">\n"); //NOI18N
+ dumpSequence(ts, sb);
+ sb.append("--------------------------------------------\n\n");
//NOI18N
+
+ LOG.finest(sb.toString());
+ }
+
+ fireHighlightsChange(evt.affectedStartOffset(),
evt.affectedEndOffset());
+// fireHighlightsChange(0, Integer.MAX_VALUE);
+ }
+
+ // ----------------------------------------------------------------------
+ // Private implementation
+ // ----------------------------------------------------------------------
+
+ // XXX: This hack is here to make sure that preview panels in Tools-Options
+ // work. Currently there is no way how to force a particular JTextComponent
+ // to use a particular MimeLookup. They all use MimeLookup common for all
components
+ // and for the mime path of things displayed in that component. The
preview panels
+ // however need special MimeLookup that loads colorings from a special
profile
+ // (i.e. not the currently active coloring profile, which is used normally
by
+ // all the other components).
+ //
+ // The hack is that Tools-Options modifies mime type of the document loaded
+ // in the preview panel and prepend 'textXXXX_' at the beginning. The
normal
+ // MimeLookup for this mime type and any mime path derived from this mime
type
+ // is empty. The editor/settings/storage however provides a special
handling
+ // for these 'test' mime paths and bridge them to the MimeLookup that you
would
+ // normally get for the mime path without the 'testXXXX_' at the
beginning, plus
+ // they supply special colorings from the profile called 'testXXXX'. This
way
+ // the preview panels can have different colorings from the rest of the
IDE.
+ //
+ // This is obviously very fragile and not fully transparent for clients as
+ // you can see here. We need a better solution for that. Generally it
should
+ // be posible to ask somewhere for a component-specific MimeLookup. This
would
+ // normally be a standard MimeLookup as you know it, but in special cases
it
+ // could be modified by the client code that created the component - e.g.
Tools-Options
+ // panel.
+ private String languagePathToMimePathOptions(LanguagePath languagePath) {
+ if (languagePath.size() == 1) {
+ return mimeTypeForOptions;
+ } else if (languagePath.size() > 1) {
+ return mimeTypeForOptions + "/" +
languagePath.subPath(1).mimePath(); //NOI18N
+ } else {
+ throw new IllegalStateException("LanguagePath should not be
empty."); //NOI18N
+ }
+ }
+
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ fireHighlightsChange(0, Integer.MAX_VALUE); // Recompute highlights
for whole document
+ }
+
+ synchronized long getVersion() {
+ return version;
+ }
+
+ private <T extends TokenId> FCSInfo<T> findFCSInfo(String mimePath,
Language<T> language) {
+ @SuppressWarnings("unchecked")
+ FCSInfo<T> fcsInfo = (FCSInfo<T>) fcsCache.get(mimePath); // Search
local cache
+ if (fcsInfo == null) { // Search in global cache
+ synchronized (globalFCSCache) {
+ @SuppressWarnings("unchecked")
+ FCSInfo<T> fcsI = (FCSInfo<T>) globalFCSCache.get(mimePath);
+ fcsInfo = fcsI;
+ if (fcsInfo == null) {
+ fcsInfo = new FCSInfo<T>(mimePath, language);
+ if (mimeTypeForOptions == null) { // Only cache non-test
ones globally
+ globalFCSCache.put(mimePath, fcsInfo);
+ }
+ }
+ }
+ fcsInfo.addChangeListener(WeakListeners.change(this, fcsInfo));
+ fcsCache.put(mimePath, fcsInfo);
+ }
+ return fcsInfo;
+ }
+
+ private static void dumpSequence(TokenSequence<?> seq, StringBuilder sb) {
+ if (seq == null) {
+ sb.append("Inactive TokenHierarchy"); //NOI18N
+ } else {
+ for(seq.moveStart(); seq.moveNext(); ) {
+ TokenSequence<?> emSeq = seq.embedded();
+ if (emSeq != null) {
+ dumpSequence(emSeq, sb);
+ } else {
+ Token<?> token = seq.token();
+ sb.append("<"); //NOI18N
+ sb.append(String.format("%3s", seq.offset())).append(",
"); //NOI18N
+ sb.append(String.format("%3s", seq.offset() +
token.length())).append(", "); //NOI18N
+ sb.append(String.format("%+3d", token.length())).append(">
: "); //NOI18N
+ sb.append(tokenId(token.id(), true)).append(" : '");
//NOI18N
+ sb.append(tokenText(token));
+ sb.append("'\n"); //NOI18N
+ }
+ }
+ }
+ }
+
+ private static String tokenId(TokenId tokenId, boolean format) {
+ if (format) {
+ return String.format("%20s.%-15s",
tokenId.getClass().getSimpleName(), tokenId.name()); //NOI18N
+ } else {
+ return tokenId.getClass().getSimpleName() + "." + tokenId.name();
//NOI18N
+ }
+ }
+
+ private static String tokenText(Token<?> token) {
+ CharSequence text = token.text();
+ StringBuilder sb = new StringBuilder(text.length());
+
+ for(int i = 0; i < text.length(); i++) {
+ char ch = text.charAt(i);
+ if (Character.isISOControl(ch)) {
+ switch (ch) {
+ case '\n' : sb.append("\\n"); break; //NOI18N
+ case '\t' : sb.append("\\t"); break; //NOI18N
+ case '\r' : sb.append("\\r"); break; //NOI18N
+ default : sb.append("\\").append(Integer.toOctalString(ch));
break; //NOI18N
+ }
+ } else {
+ sb.append(ch);
+ }
+ }
+
+ return sb.toString();
+ }
+
+ private static String attributeSet(AttributeSet as) {
+ if (as == null) {
+ return "AttributeSet is null"; //NOI18N
+ }
+
+ StringBuilder sb = new StringBuilder();
+
+ for(Enumeration<? extends Object> keys = as.getAttributeNames();
keys.hasMoreElements(); ) {
+ Object key = keys.nextElement();
+ Object value = as.getAttribute(key);
+
+ if (key == null) {
+ sb.append("null"); //NOI18N
+ } else {
+ sb.append("'").append(key.toString()).append("'"); //NOI18N
+ }
+
+ sb.append(" = "); //NOI18N
+
+ if (value == null) {
+ sb.append("null"); //NOI18N
+ } else {
+ sb.append("'").append(value.toString()).append("'"); //NOI18N
+ }
+
+ if (keys.hasMoreElements()) {
+ sb.append(", "); //NOI18N
+ }
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Checks if the token should be treated as a block. Returns true if the
token
+ * does NOT representa a block. Blocks are highlighted as a whole,
including
+ * free space after the trailing whitespaces on the line.
+ *
+ * @param t token to check
+ * @return true, if token is normal text; false if block.
+ */
+ private static boolean noBlock(Token t) {
+ return t.getProperty("highlight.block") != Boolean.TRUE; // NOI18N
+ }
+
+ private final class HSImpl implements HighlightsSequence {
+
+ private static final int S_INIT = 0;
+ private static final int S_TOKEN = 1; // Attempt to branch current
token
+ private static final int S_NEXT_TOKEN = 2; // Fetch next token
+ private static final int S_EMBEDDED_HEAD = 3; // On head of an
embedding (in front of its first token)
+ private static final int S_EMBEDDED_TAIL = 4; // Just above last token
of the embedding
+ private static final int S_DONE = 5;
+
+ private final long version;
+ private final TokenHierarchy<? extends Document> scanner;
+ private final int startOffset;
+ private final int endOffset;
+ private final CharSequence docText;
+ private int newlineOffset;
+ private int partsEndOffset; // In case '\n' is in the middle of token
this is end offset of the whole token
+
+ // Last found highlight's startOffset, endOffset and attributes
+ private int hiStartOffset;
+ private int hiEndOffset;
+ private AttributeSet hiAttrs;
+
+ private List<TSInfo<?>> sequences;
+ private int state = S_INIT;
+ private LogHelper logHelper;
+
+ public HSImpl(long version, TokenHierarchy<? extends Document>
scanner, int startOffset, int endOffset) {
+ this.version = version;
+ this.scanner = scanner;
+ startOffset = Math.max(startOffset, 0); // Tests may request
Integer.MIN_VALUE for startOffset
+ this.startOffset = startOffset;
+ this.sequences = new ArrayList<TSInfo<?>>(4);
+ this.hiStartOffset = startOffset;
+ this.hiEndOffset = startOffset;
+ Document doc = scanner.inputSource();
+ this.docText = DocumentUtilities.getText(doc);
+ endOffset = Math.min(endOffset, docText.length());
+ this.endOffset = endOffset;
+ newlineOffset = -1;
+ updateNewlineOffset(startOffset);
+ @SuppressWarnings("unchecked")
+ TokenSequence<TokenId> seq = (TokenSequence<TokenId>)
scanner.tokenSequence();
+ if (seq != null) {
+ seq.move(startOffset);
+ TSInfo<TokenId> tsInfo = new TSInfo<TokenId>(seq);
+ sequences.add(tsInfo);
+ state = S_NEXT_TOKEN;
+ } else {
+ state = S_DONE;
+ }
+ if (LOG.isLoggable(Level.FINE)) {
+ logHelper = new LogHelper();
+ logHelper.startTime = System.currentTimeMillis();
+ LOG.fine("SyntaxHighlighting.HSImpl <" + startOffset + "," +
endOffset + ">\n"); // NOI18N
+ if (LOG.isLoggable(Level.FINEST)) {
+ LOG.log(Level.FINEST, "Highlighting caller", new
Exception()); // NOI18N
+ }
+ }
+ }
+
+ public @Override boolean moveNext() {
+ if (state == S_DONE) {
+ return false;
+ }
+
+ if (SyntaxHighlighting.this.getVersion() != this.version) {
+ finish();
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("SyntaxHighlighting: Version changed => HSImpl
finished at offset=" + hiEndOffset); // NOI18N
+ }
+ return false;
+ }
+
+ // Check whether processing multiple parts into that token was
split due to presence of '\n' char(s)
+ if (partsEndOffset != 0) { // Fetch next part
+ while (hiEndOffset == newlineOffset) { // Newline at highlight
start
+ hiEndOffset++; // Skip newline
+ if (updateNewlineOffset(hiEndOffset)) { // Reached
endOffset
+ finish();
+ return false;
+ }
+ if (hiEndOffset >= partsEndOffset) { // Reached end of
parts only by newlines
+ finishParts();
+ return moveTheSequence();
+ }
+ }
+ hiStartOffset = hiEndOffset;
+ if (newlineOffset < partsEndOffset) {
+ hiEndOffset = newlineOffset;
+ } else {
+ hiEndOffset = partsEndOffset;
+ finishParts();
+ }
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine(" SH.moveNext(): part-Highlight: <" +
hiStartOffset + "," + // NOI18N
+ hiEndOffset + "> attrs=" + hiAttrs + " " +
stateToString() + // NOI18N
+ ", pEOffset=" + partsEndOffset + ", seq#=" +
sequences.size() + "\n"); // NOI18N
+ }
+ return true;
+ } else if (hiEndOffset >= newlineOffset) {
+ updateNewlineOffset(hiEndOffset);
+ }
+
+ return moveTheSequence();
+ }
+
+ public @Override int getStartOffset() {
+ return hiStartOffset;
+ }
+
+ public @Override int getEndOffset() {
+ return hiEndOffset;
+ }
+
+ public @Override AttributeSet getAttributes() {
+ return hiAttrs;
+ }
+
+ private boolean moveTheSequence() {
+ boolean done = false;
+ boolean log = LOG.isLoggable(Level.FINE);
+ do {
+ TSInfo<?> tsInfo = sequences.get(sequences.size() - 1);
+ switch (state) {
+ case S_TOKEN:
+ TokenSequence<?> embeddedSeq = tsInfo.ts.embedded();
+ if (embeddedSeq != null) {
+ @SuppressWarnings("unchecked")
+ TSInfo<TokenId> embeddedTSInfo = new
TSInfo<TokenId>((TokenSequence<TokenId>) embeddedSeq);
+ sequences.add(embeddedTSInfo);
+ if (embeddedTSInfo.moveNextToken(startOffset,
endOffset)) { // Embedded token sequence has at least one token
+ int headLen = embeddedTSInfo.tokenOffset -
hiEndOffset;
+ if (headLen > 0) {
+ state = S_EMBEDDED_HEAD;
+ done =
assignHighlightOrPart(embeddedTSInfo.tokenOffset, tsInfo.tokenAttrs,
noBlock(tsInfo.ts.token()));
+ if (log) {
+ LOG.fine(" S_TOKEN -> S_EMBEDDED_HEAD,
token<" + tsInfo.tokenOffset + // NOI18N
+ "," + tsInfo.tokenEndOffset +
"> headLen=" + headLen + "\n"); // NOI18N
+ }
+ } // else: No head -> attempt further nested
embedding on current emb.token
+ } else { // No tokens in embedded sequence
+ state = S_EMBEDDED_TAIL;
+ done = assignHighlightOrPart(tsInfo);
+ if (log) {
+ LOG.fine(" S_TOKEN -> S_EMBEDDED_TAIL\n");
+ }
+ }
+ } else { // embeddedSeq == null
+ state = S_NEXT_TOKEN;
+ done = assignHighlightOrPart(tsInfo);
+ }
+ break;
+
+ case S_NEXT_TOKEN:
+ if (tsInfo.moveNextToken(startOffset, endOffset)) {
+ state = S_TOKEN;
+ if (log) {
+ logHelper.tokenCount++;
+ }
+ } else { // No more tokens
+ if (sequences.size() > 1) {
+ TSInfo<?> outerTSInfo =
sequences.get(sequences.size() - 2);
+ state = S_EMBEDDED_TAIL;
+ if (tsInfo.tokenEndOffset <
outerTSInfo.tokenEndOffset) {
+ done = assignHighlightOrPart(outerTSInfo);
+ }
+ } else { // Outer sequence => stop processing
+ sequences.clear();
+ finish();
+ if (log) {
+ LOG.fine("SyntaxHighlighting: " +
scanner.inputSource() + //NOI18N
+ ":\n-> returned " +
logHelper.tokenCount + " token highlights for <" + //NOI18N
+ startOffset + "," + endOffset +
//NOI18N
+ "> in " + //NOI18N
+ (System.currentTimeMillis() -
logHelper.startTime) + " ms.\n"); //NOI18N
+ LOG.finer(tsInfo.ts.toString());
+ LOG.fine("\n");
+ }
+ return false;
+ }
+ }
+ break;
+
+ case S_EMBEDDED_HEAD:
+ // Current token contains embedded language and we
have processed its head
+ // First token is fetched already so just use it.
+ state = S_TOKEN;
+ break;
+
+ case S_EMBEDDED_TAIL:
+ // The current token contains embedded language and we
have processed it's tail
+ state = S_NEXT_TOKEN;
+ sequences.remove(sequences.size() - 1);
+ if (log) {
+ LOG.fine("S_EMBEDDED_TAIL -> S_NEXT_TOKEN;
sequences.size()=" + sequences.size() + "\n"); // NOI18N
+ }
+ break;
+
+ default: // Includes S_INIT and S_DONE
+ throw new IllegalStateException("Invalid state: " +
state); //NOI18N
+ }
+ } while (!done);
+
+ if (log) {
+ LOG.fine("SH.moveTheSequence(): Highlight: <" + hiStartOffset
+ "," + hiEndOffset + // NOI18N
+ "> attrs=" + hiAttrs + " " + stateToString() + ",
seq#=" + sequences.size() + "\n"); // NOI18N
+ }
+ return true; // Highlight assigned
+ }
+
+ private boolean assignHighlightOrPart(TSInfo<?> tsInfo) {
+ return assignHighlightOrPart(tsInfo.tokenEndOffset,
tsInfo.tokenAttrs, noBlock(tsInfo.ts.token()));
+ }
+
+ /**
+ * Assign full token or its initial part as a next highlight.
+ *
+ * @param tokenEndOffset
+ * @param attrs
+ * @return true if highlight was assigned successfully or false if it
could not be assigned
+ * due to token consisting of all newlines.
+ */
+ private boolean assignHighlightOrPart(int tokenEndOffset, AttributeSet
attrs, boolean noBlock) {
+ if (noBlock) {
+ while (hiEndOffset == newlineOffset) { // Newline at highlight
start
+ hiEndOffset++; // Skip newline
+ if (updateNewlineOffset(hiEndOffset) || hiEndOffset >=
tokenEndOffset) { // Reached endOffset
+ hiStartOffset = hiEndOffset;
+ return false;
+ }
+ }
+ }
+ hiStartOffset = hiEndOffset;
+ if (hiEndOffset >= tokenEndOffset) {
+ hiStartOffset = hiEndOffset;
+ return false;
+ }
+ if (noBlock && newlineOffset >= hiStartOffset && newlineOffset <
tokenEndOffset) {
+ hiEndOffset = newlineOffset;
+ partsEndOffset = tokenEndOffset;
+ } else {
+ hiEndOffset = tokenEndOffset;
+ }
+ hiAttrs = attrs;
+ return true;
+ }
+
+ /**
+ * Update newlineOffset.
+ *
+ * @param offset scan start offset. If '\n' right at offset then
+ * newlineOffset will be == offset.
+ */
+ private boolean updateNewlineOffset(int offset) {
+ while (offset < endOffset) {
+ if (docText.charAt(offset) == '\n') {
+ newlineOffset = offset;
+ return false;
+ }
+ offset++;
+ }
+ newlineOffset = endOffset;
+ return true;
+ }
+
+ private void finishParts() {
+ partsEndOffset = 0;
+ }
+
+ private void finish() {
+ state = S_DONE;
+ hiStartOffset = endOffset;
+ hiEndOffset = endOffset;
+ hiAttrs = null;
+ }
+
+ private String stateToString() {
+ switch (state) {
+ case S_INIT:
+ return "S_INIT"; // NOI18N
+ case S_TOKEN:
+ return "S_TOKEN"; // NOI18N
+ case S_NEXT_TOKEN:
+ return "S_NEXT_TOKEN"; // NOI18N
+ case S_EMBEDDED_HEAD:
+ return "S_EMBEDDED_HEAD"; // NOI18N
+ case S_EMBEDDED_TAIL:
+ return "S_EMBEDDED_TAIL"; // NOI18N
+ case S_DONE:
+ return "S_DONE"; // NOI18N
+ default:
+ throw new IllegalStateException("Unknown state=" + state);
// NOI18N
+ }
+ }
+
+ } // End of HSImpl class
+
+ private static final class LogHelper {
+
+ int tokenCount;
+ long startTime;
+ }
+
+ //for tests:
+ static AttributeSet TEST_FALLBACK_COLORING;
+
+ private static final class FCSInfo<T extends TokenId> implements
LookupListener {
+
+ private volatile ChangeEvent changeEvent;
+
+ private final Language<T> innerLanguage;
+
+ private final String mimePath; // Can start with mimeTypeForOptions
+
+ private final ListenerList<ChangeListener> listeners;
+
+ private final Lookup.Result<FontColorSettings> result;
+
+ private AttributeSet[] tokenId2attrs;
+
+ FontColorSettings fcs;
+
+ /**
+ * @param innerLanguage
+ * @param mimePath note it may start with mimeTypeForOptions
+ */
+ public FCSInfo(String mimePath, Language<T> innerLanguage) {
+ this.innerLanguage = innerLanguage;
+ this.mimePath = mimePath;
+ this.listeners = new ListenerList<ChangeListener>();
+ Lookup lookup = MimeLookup.getLookup("text/textmate");
+ result = lookup.lookupResult(FontColorSettings.class);
+ // Do not listen on font color settings changes in tests
+ // since "random" lookup events translate into highlight change
events
+ // that are monitored by tests and so the tests may then fail
+ if (TEST_FALLBACK_COLORING == null) {
+
result.addLookupListener(WeakListeners.create(LookupListener.class, this,
result));
+ }
+ updateFCS();
+ }
+
+ private static final Map<String, AttributeSet> scopeName2Coloring =
new HashMap<>();
+
+ /**
+ * @param token non-null token.
+ * @return attributes for tokenId or null if none found.
+ */
+ synchronized AttributeSet findAttrs(Token token) {
+ if (token.id() != TextmateTokenId.TEXTMATE) {
+ return null;
+ }
+
+ List<AttributeSet> attrs = new ArrayList<>();
+ List<String> categories = (List<String>)
token.getProperty("categories");
+
+ for (String category : categories) {
+ attrs.add(scopeName2Coloring.computeIfAbsent(category, c -> {
+ String cat = category;
+
+ while (true) {
+ AttributeSet currentAttrs =
fcs.getTokenFontColors(cat);
+
+ if (currentAttrs != null) {
+ return currentAttrs;
+ }
+
+ int dot = cat.lastIndexOf('.');
+
+ if (dot == (-1))
+ break;
+
+ cat = cat.substring(0, dot);
+ }
+
+ return SimpleAttributeSet.EMPTY;
+ }));
+ }
+
+ return AttributesUtilities.createComposite(attrs.toArray(new
AttributeSet[0]));
+ }
+
+ public void addChangeListener(ChangeListener l) {
+ listeners.add(l);
+ }
+
+ public void removeChangeListener(ChangeListener l) {
+ listeners.remove(l);
+ }
+
+ private void updateFCS() {
+ FontColorSettings newFCS = result.allInstances().iterator().next();
+ if (newFCS == null && LOG.isLoggable(Level.WARNING)) {
+ // Should not normally happen; see #106337
+ LOG.warning("No FontColorSettings for '" + mimePath + "' mime
path."); //NOI18N
+ }
+ synchronized (this) {
+ fcs = newFCS;
+ if (innerLanguage != null) {
+ tokenId2attrs = new
AttributeSet[innerLanguage.maxOrdinal() + 1];
+ }
+ }
+ }
+
+ private ChangeEvent createChangeEvent() {
+ if (changeEvent == null) {
+ changeEvent = new ChangeEvent(this);
+ }
+ return changeEvent;
+ }
+
+ @Override
+ public void resultChanged(LookupEvent ev) {
+ updateFCS();
+ ChangeEvent e = createChangeEvent();
+ for (ChangeListener l : listeners.getListeners()) {
+ l.stateChanged(e);
+ }
+ }
+
+ }
+
+ private final class TSInfo<T extends TokenId> {
+
+ final TokenSequence<T> ts;
+
+ final FCSInfo<T> fcsInfo;
+
+ int tokenOffset;
+
+ int tokenEndOffset;
+
+ AttributeSet tokenAttrs;
+
+ /**
+ * @param ts
+ */
+ public TSInfo(TokenSequence<T> ts) {
+ this.ts = ts;
+ LanguagePath languagePath = ts.languagePath();
+ @SuppressWarnings("unchecked")
+ Language<T> innerLanguage =
(Language<T>)languagePath.innerLanguage();
+ String mimePathExt;
+ if (mimeTypeForOptions != null) {
+ // First mime-type in mimePath starts with "test"
+ mimePathExt = languagePathToMimePathOptions(languagePath);
+ } else {
+ mimePathExt = languagePath.mimePath();
+ }
+
+ fcsInfo = findFCSInfo(mimePathExt, innerLanguage);
+ }
+
+ boolean moveNextToken(int limitStartOffset, int limitEndOffset) {
+ if (ts.moveNext()) {
+ Token<T> token = ts.token();
+ int nextTokenOffset = ts.offset();
+ if (nextTokenOffset < 0) {
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Invalid token offset=" + nextTokenOffset + "
< 0. TokenSequence:\n" + ts); // NOI18N
+ }
+ return false;
+ }
+ int nextTokenLength = token.length();
+ if (nextTokenOffset < 0) {
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Invalid token length=" + nextTokenLength + "
< 0. TokenSequence:\n" + ts); // NOI18N
+ }
+ return false;
+ }
+ if (nextTokenOffset >= tokenEndOffset || nextTokenLength >= 0)
{
+ tokenOffset = nextTokenOffset;
+ tokenEndOffset = tokenOffset + nextTokenLength;
+ } else {
+ // Become robust against an invalid lexer's output by
returning "no more tokens" here
+ return false;
+ }
+ if (tokenEndOffset <= limitStartOffset) {
+ // Must move the sequence forward by bin-search
+ ts.move(limitStartOffset);
+ if (!ts.moveNext()) { // limitStartOffset above tokens (in
tail section)
+ return false;
+ }
+ token = ts.token();
+ tokenOffset = ts.offset();
+ tokenEndOffset = tokenOffset + token.length();
+ }
+ tokenOffset = Math.max(tokenOffset, limitStartOffset);
+ T id = token.id();
+ if (tokenEndOffset > limitEndOffset) {
+ if (tokenOffset >= limitEndOffset) {
+ return false;
+ } else {
+ tokenEndOffset = limitEndOffset;
+ }
+ }
+ tokenAttrs = fcsInfo.findAttrs(token);
+
+ if (LOG.isLoggable(Level.FINE)) {
+ // Add token info to the tooltip
+ tokenAttrs = AttributesUtilities.createComposite(
+
AttributesUtilities.createImmutable(EditorStyleConstants.Tooltip,
+ "<html>" //NOI18N
+ + "<b>Token:</b> " + token.text() //NOI18N
+ + "<br><b>Id:</b> " + id.name() //NOI18N
+ + "<br><b>Category:</b> " + id.primaryCategory()
//NOI18N
+ + "<br><b>Ordinal:</b> " + id.ordinal() //NOI18N
+ + "<br><b>Mimepath:</b> " +
ts.languagePath().mimePath() //NOI18N
+ ),
+ tokenAttrs);
+ }
+ return true;
+ } else {
+ tokenOffset = tokenEndOffset;
+ return false;
+ }
+ }
+
+ }
+
+ @MimeRegistration(service=HighlightsLayerFactory.class, mimeType="")
+ public static class FactoryImpl implements HighlightsLayerFactory {
+
+ @Override
+ public HighlightsLayer[] createLayers(Context ctx) {
+ Document doc = ctx.getDocument();
+ TokenHierarchy<Document> th = TokenHierarchy.get(doc);
+
+ if (th == null) {
+ return new HighlightsLayer[0];
+ }
+ //check the token hierarchy produces the TextmateTokens
+ return new HighlightsLayer[] {
+ HighlightsLayer.create(SyntaxHighlighting.class.getName(),
+ ZOrder.SYNTAX_RACK,
+ true,
+ new SyntaxHighlighting(doc))
+ };
+ }
+
+ }
+}
diff --git
a/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/TextmateLexer.java
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/TextmateLexer.java
new file mode 100644
index 0000000..168c459
--- /dev/null
+++
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/TextmateLexer.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.textmate.lexer;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+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.netbeans.api.lexer.Token;
+import org.netbeans.spi.lexer.Lexer;
+import org.netbeans.spi.lexer.LexerInput;
+import org.netbeans.spi.lexer.TokenFactory;
+
+public class TextmateLexer implements Lexer<TextmateTokenId>{
+
+ private static final Object DO_NOT_RESUME_HERE = new Object();
+
+ private final LexerInput li;
+ private final TokenFactory<TextmateTokenId> factory;
+ private final IGrammar grammar;
+ private int lineLen;
+ private int currentOffset;
+ private List<IToken> lineTokens;
+ private int currentIdx;
+ private StackElement state;
+
+ public TextmateLexer(LexerInput li, Object state,
TokenFactory<TextmateTokenId> factory, IGrammar grammar) {
+ if (state == DO_NOT_RESUME_HERE) {
+ throw new IllegalStateException("Invalid resume state!");
+ }
+ this.li = li;
+ this.state = (StackElement) state;
+ this.factory = factory;
+ this.grammar = grammar;
+ }
+
+ @Override
+ public Token<TextmateTokenId> nextToken() {
+ if (currentOffset >= lineLen) {
+ //read next line:
+ int read;
+ while ((read = li.read()) != LexerInput.EOF && read != '\n');
+ if (li.readLength() != 0) {
+ System.err.println(li.readText().toString());
+ lineLen = li.readText().length();
+ currentOffset = 0;
+ ITokenizeLineResult tokenized =
grammar.tokenizeLine(li.readText().toString(), state);
+ lineTokens = new
ArrayList<>(Arrays.asList(tokenized.getTokens()));
+ currentIdx = 0;
+ state = tokenized.getRuleStack();
+ }
+ }
+ if (lineTokens != null && currentIdx < lineTokens.size()) {
+ IToken current = lineTokens.get(currentIdx);
+ if (currentOffset < current.getStartIndex()) {
+ int len = current.getStartIndex() - currentOffset;
+ currentOffset += len;
+ return factory.createToken(TextmateTokenId.UNTOKENIZED,
lineLen - currentOffset);
+ } else if (currentOffset == current.getStartIndex()) {
+ currentIdx++;
+ int len = current.getEndIndex() - current.getStartIndex();
+ len = Math.min(len, lineLen - currentOffset); //XXX:
untested, unclear when this happens (Rust)
+ currentOffset += len;
+ List<String> categories = Collections.unmodifiableList(new
ArrayList<>(current.getScopes()));
+ return factory.createPropertyToken(TextmateTokenId.TEXTMATE,
len, (token, key) -> {
+ if ("categories".equals(key)) {
+ return categories;
+ } else {
+ return null;
+ }
+ });
+ }
+ }
+ if (currentOffset < lineLen) {
+ int len = lineLen - currentOffset;
+ currentOffset += len;
+ return factory.createToken(TextmateTokenId.UNTOKENIZED, len);
+ }
+ return null;
+ }
+
+ @Override
+ public Object state() {
+ return lineLen != currentOffset ? DO_NOT_RESUME_HERE : this.state;
+ }
+
+ @Override
+ public void release() {}
+
+}
diff --git
a/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/TextmateTokenId.java
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/TextmateTokenId.java
new file mode 100644
index 0000000..152ffba
--- /dev/null
+++
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/TextmateTokenId.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.textmate.lexer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.eclipse.tm4e.core.grammar.IGrammar;
+import org.eclipse.tm4e.core.registry.IRegistryOptions;
+import org.eclipse.tm4e.core.registry.Registry;
+import org.netbeans.api.editor.mimelookup.MimePath;
+import org.netbeans.api.lexer.TokenId;
+import org.netbeans.spi.editor.mimelookup.MimeDataProvider;
+import org.netbeans.spi.lexer.LanguageHierarchy;
+import org.netbeans.spi.lexer.Lexer;
+import org.netbeans.spi.lexer.LexerRestartInfo;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+import org.openide.util.lookup.ServiceProvider;
+
+public enum TextmateTokenId implements TokenId {
+
+ TEXTMATE,
+ UNTOKENIZED;
+
+ @Override
+ public String primaryCategory() {
+ return "textmate";
+ }
+
+ public static class LanguageHierarchyImpl extends
LanguageHierarchy<TextmateTokenId> {
+
+ public static final String GRAMMAR_MARK = "textmate-grammar";
+ private static final Map<String, FileObject> scope2File;
+ private static final Map<String, String> mimeType2Scope;
+
+ static {
+ scope2File = new HashMap<>();
+ mimeType2Scope = new HashMap<>();
+ FileObject editors =
FileUtil.getSystemConfigRoot().getFileObject("Editors");
+ if (editors != null) {
+ Enumeration<? extends FileObject> en =
editors.getChildren(true);
+ while (en.hasMoreElements()) {
+ FileObject candidate = en.nextElement();
+ Object attr = candidate.getAttribute(GRAMMAR_MARK);
+ if (attr != null && attr instanceof String) {
+ String scope = (String) attr;
+ scope2File.put(scope, candidate);
+ mimeType2Scope.put(FileUtil.getRelativePath(editors,
candidate.getParent()), scope);
+ }
+ }
+ }
+ }
+
+ private final String mimeType;
+ private final IGrammar grammar;
+
+ public LanguageHierarchyImpl(String mimeType, String scope) throws
Exception {
+ this.mimeType = mimeType;
+ IRegistryOptions opts = new IRegistryOptions() {
+ @Override
+ public String getFilePath(String scopeName) {
+ FileObject file = scope2File.get(scopeName);
+ return file != null ? file.getNameExt() : null;
+ }
+ @Override
+ public InputStream getInputStream(String scopeName) throws
IOException {
+ FileObject file = scope2File.get(scopeName);
+ return file != null ? file.getInputStream(): null;
+ }
+ @Override
+ public Collection<String> getInjections(String scopeName) {
+ return null;
+ }
+ };
+ this.grammar = new Registry(opts).loadGrammar(scope);
+ }
+
+ @Override
+ protected Collection<TextmateTokenId> createTokenIds() {
+ return Arrays.asList(TextmateTokenId.values());
+ }
+
+ @Override
+ protected Lexer<TextmateTokenId>
createLexer(LexerRestartInfo<TextmateTokenId> lri) {
+ return new TextmateLexer(lri.input(), lri.state(),
lri.tokenFactory(), grammar);
+ }
+
+ @Override
+ protected String mimeType() {
+ return mimeType;
+ }
+
+ }
+
+ @ServiceProvider(service=MimeDataProvider.class,
position=Integer.MAX_VALUE)
+ public static final class MimeDataProviderImpl implements MimeDataProvider
{
+
+ private static final Logger LOG =
Logger.getLogger(MimeDataProviderImpl.class.getName());
+
+ @Override
+ public Lookup getLookup(MimePath arg0) {
+ String scope =
LanguageHierarchyImpl.mimeType2Scope.get(arg0.getPath());
+
+ if (scope != null) {
+ try {
+ return Lookups.singleton(new
LanguageHierarchyImpl(arg0.getPath(), scope).language());
+ } catch (Exception ex) {
+ LOG.log(Level.FINE, null, ex);
+ }
+ }
+
+ return null;
+ }
+
+ }
+}
diff --git
a/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/Bundle.properties
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/Bundle.properties
new file mode 100644
index 0000000..b0c3230
--- /dev/null
+++
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/Bundle.properties
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+text/textmate=TextMate Languages
diff --git
a/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/fontsColors.xml
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/fontsColors.xml
new file mode 100644
index 0000000..be6e632
--- /dev/null
+++
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/fontsColors.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License") /> you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<!DOCTYPE fontscolors PUBLIC "-//NetBeans//DTD Editor Fonts and Colors
settings 1.1//EN" "http://www.netbeans.org/dtds/EditorFontsColors-1_1.dtd">
+
+<fontscolors>
+
+ <fontcolor name="comment" default="comment" />
+ <fontcolor name="constant.numeric" default="number" />
+ <fontcolor name="constant.character" default="char" />
+ <fontcolor name="constant.character.escape" default="char">
+ <font style="bold" />
+ </fontcolor>
+ <fontcolor name="constant.language" default="keyword" />
+ <fontcolor name="constant.other" default="identifier" /> <!--???-->
+ <fontcolor name="entity.name.function" default="method">
+ <font style="bold" />
+ </fontcolor>
+ <fontcolor name="invalid" default="error" />
+ <fontcolor name="keyword" default="keyword" />
+ <fontcolor name="keyword.operator" default="operator" />
+ <fontcolor name="markup.underline" underline="000000"/>
+ <fontcolor name="markup.bold" default="identifier">
+ <font style="bold" />
+ </fontcolor>
+ <fontcolor name="markup.heading" default="identifier">
+ <font style="bold" />
+ </fontcolor>
+ <fontcolor name="markup.italic" default="identifier">
+ <font style="italic" />
+ </fontcolor>
+ <fontcolor name="storage" default="keyword" />
+ <fontcolor name="string" default="string" />
+ <fontcolor name="support.function" default="method" />
+ <fontcolor name="support.constant" default="keyword" />
+ <fontcolor name="variable.language" default="keyword" />
+
+</fontscolors>
diff --git
a/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/layer.xml
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/layer.xml
new file mode 100644
index 0000000..a24c4c0
--- /dev/null
+++
b/ide/textmate.lexer/src/org/netbeans/modules/textmate/lexer/resources/layer.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License") /> you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN"
"http://www.netbeans.org/dtds/filesystem-1_2.dtd">
+<filesystem>
+ <folder name="Editors">
+ <folder name="text">
+ <folder name="textmate">
+ <attr name="SystemFileSystem.localizingBundle"
stringvalue="org.netbeans.modules.textmate.lexer.resources.Bundle"/>
+ <folder name="FontsColors">
+ <folder name="NetBeans">
+ <folder name="Defaults">
+ <file name="fontsColors.xml" url="fontsColors.xml">
+ </file>
+ </folder>
+ </folder>
+ </folder>
+ </folder>
+ </folder>
+ </folder>
+</filesystem>
+
diff --git
a/ide/textmate.lexer/test/unit/src/org/netbeans/modules/textmate/lexer/TextmateLexerTest.java
b/ide/textmate.lexer/test/unit/src/org/netbeans/modules/textmate/lexer/TextmateLexerTest.java
new file mode 100644
index 0000000..a448cfc
--- /dev/null
+++
b/ide/textmate.lexer/test/unit/src/org/netbeans/modules/textmate/lexer/TextmateLexerTest.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.textmate.lexer;
+
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.Arrays;
+import javax.swing.text.Document;
+import javax.swing.text.PlainDocument;
+import org.netbeans.api.lexer.Language;
+import org.netbeans.api.lexer.TokenHierarchy;
+import org.netbeans.api.lexer.TokenSequence;
+import org.netbeans.junit.NbTestCase;
+import org.netbeans.lib.lexer.test.LexerTestUtilities;
+import
org.netbeans.modules.textmate.lexer.TextmateTokenId.LanguageHierarchyImpl;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+
+public class TextmateLexerTest extends NbTestCase {
+
+ public TextmateLexerTest(String name) {
+ super(name);
+ }
+
+ public void testRestart() throws Exception {
+ clearWorkDir();
+
+ FileObject grammar = FileUtil.createData(FileUtil.getConfigRoot(),
"Editors/text/test/grammar.json");
+ try (OutputStream out = grammar.getOutputStream();
+ Writer w = new OutputStreamWriter(out)) {
+ w.write("{ \"scopeName\": \"test\", " +
+ " \"patterns\": [\n" +
+ " { \"name\": \"string.test\",\n" +
+ " \"begin\": \"x([^x]+)x\",\n" +
+ " \"end\": \"x\\\\1x\"\n" +
+ " },\n" +
+ " { \"name\": \"whitespace.test\",\n" +
+ " \"match\": \" +\"\n" +
+ " }\n" +
+ "]}\n");
+ }
+ grammar.setAttribute(LanguageHierarchyImpl.GRAMMAR_MARK, "test");
+ Document doc = new PlainDocument();
+ doc.insertString(0, " xaax xbbx\nxccx xaax ", null);
+ doc.putProperty(Language.class, new LanguageHierarchyImpl("text/test",
"test").language());
+ TokenHierarchy<Document> hi = TokenHierarchy.get(doc);
+ TokenSequence<?> ts = hi.tokenSequence();
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" ");
+ assertTokenProperties(ts, "test", "whitespace.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
"xaax");
+ assertTokenProperties(ts, "test", "string.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" xbbx\n");
+ assertTokenProperties(ts, "test", "string.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
"xccx ");
+ assertTokenProperties(ts, "test", "string.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
"xaax");
+ assertTokenProperties(ts, "test", "string.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" ");
+ assertTokenProperties(ts, "test", "whitespace.test");
+ LexerTestUtilities.assertNextTokenEquals(ts,
TextmateTokenId.UNTOKENIZED, "\n");
+ assertFalse(ts.moveNext());
+ doc.insertString(8, "b", null);
+ ts = hi.tokenSequence();
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" ");
+ assertTokenProperties(ts, "test", "whitespace.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
"xaax");
+ assertTokenProperties(ts, "test", "string.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" xbbbx\n");
+ assertTokenProperties(ts, "test", "string.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
"xccx ");
+ assertTokenProperties(ts, "test", "string.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
"xaax");
+ assertTokenProperties(ts, "test", "string.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" ");
+ assertTokenProperties(ts, "test", "whitespace.test");
+ LexerTestUtilities.assertNextTokenEquals(ts,
TextmateTokenId.UNTOKENIZED, "\n");
+ assertFalse(ts.moveNext());
+ doc.insertString(14, "c", null);
+ ts = hi.tokenSequence();
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" ");
+ assertTokenProperties(ts, "test", "whitespace.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
"xaax");
+ assertTokenProperties(ts, "test", "string.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" xbbbx\n");
+ assertTokenProperties(ts, "test", "string.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
"xcccx ");
+ assertTokenProperties(ts, "test", "string.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
"xaax");
+ assertTokenProperties(ts, "test", "string.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" ");
+ assertTokenProperties(ts, "test", "whitespace.test");
+ LexerTestUtilities.assertNextTokenEquals(ts,
TextmateTokenId.UNTOKENIZED, "\n");
+ assertFalse(ts.moveNext());
+ doc.insertString(3, "a", null);
+ ts = hi.tokenSequence();
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" ");
+ assertTokenProperties(ts, "test", "whitespace.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
"xaaax");
+ assertTokenProperties(ts, "test", "string.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" xbbbx\n");
+ assertTokenProperties(ts, "test", "string.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
"xcccx ");
+ assertTokenProperties(ts, "test", "string.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
"xaax");
+ assertTokenProperties(ts, "test", "string.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" ");
+ assertTokenProperties(ts, "test", "whitespace.test");
+ LexerTestUtilities.assertNextTokenEquals(ts,
TextmateTokenId.UNTOKENIZED, "\n");
+ assertFalse(ts.moveNext());
+ }
+
+ public void testUTF8() throws Exception {
+ clearWorkDir();
+
+ FileObject grammar = FileUtil.createData(FileUtil.getConfigRoot(),
"Editors/text/test/grammar.json");
+ try (OutputStream out = grammar.getOutputStream();
+ Writer w = new OutputStreamWriter(out)) {
+ w.write("{ \"scopeName\": \"test\", " +
+ " \"patterns\": [\n" +
+ " { \"name\": \"ident.test\",\n" +
+ " \"match\": \"[^ ]+\"\n" +
+ " }\n" +
+ "]}\n");
+ }
+ grammar.setAttribute(LanguageHierarchyImpl.GRAMMAR_MARK, "test");
+ Document doc = new PlainDocument();
+ doc.insertString(0, " večerníček večerníček \n", null);
+ doc.putProperty(Language.class, new LanguageHierarchyImpl("text/test",
"test").language());
+ TokenHierarchy<Document> hi = TokenHierarchy.get(doc);
+ TokenSequence<?> ts = hi.tokenSequence();
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" ");
+ assertTokenProperties(ts, "test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
"večerníček");
+ assertTokenProperties(ts, "test", "ident.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" ");
+ assertTokenProperties(ts, "test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
"večerníček");
+ assertTokenProperties(ts, "test", "ident.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" ");
+ assertTokenProperties(ts, "test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" ");
+ assertTokenProperties(ts, "test", "whitespace.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
"večerníček");
+ assertTokenProperties(ts, "test", "ident.test");
+ LexerTestUtilities.assertNextTokenEquals(ts, TextmateTokenId.TEXTMATE,
" ");
+ assertTokenProperties(ts, "test", "whitespace.test");
+ assertFalse(ts.moveNext());
+ }
+
+ private void assertTokenProperties(TokenSequence<?> ts, String...
properties) {
+ assertEquals(ts.token().getProperty("categories"),
Arrays.asList(properties));
+ }
+
+}
diff --git a/nbbuild/cluster.properties b/nbbuild/cluster.properties
index a557c71..088374a 100644
--- a/nbbuild/cluster.properties
+++ b/nbbuild/cluster.properties
@@ -514,6 +514,7 @@ nb.cluster.ide=\
team.ide,\
terminal,\
terminal.nb,\
+ textmate.lexer,\
usersguide,\
utilities,\
utilities.project,\
diff --git a/nbbuild/licenses/MIT-jruby b/nbbuild/licenses/MIT-jruby
new file mode 100644
index 0000000..9341f05
--- /dev/null
+++ b/nbbuild/licenses/MIT-jruby
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 JRuby Team
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/nbbuild/licenses/names.properties
b/nbbuild/licenses/names.properties
index 31ee59a..b323e0a 100644
--- a/nbbuild/licenses/names.properties
+++ b/nbbuild/licenses/names.properties
@@ -57,6 +57,7 @@ MIT-icu4j=MIT license icu4j variant
MIT-isorelax=MIT license isorelax variant
MIT-sim=MIT license ios-sim variant, with license for code from contributors.
MIT-jquery=MIT license JQuery variant
+MIT-jruby=MIT license JRuby variant
MIT-nodejs=MIT license NodeJS variant plus node external libraries licenses
MIT-phpstan=MIT license PHPStan variant
MIT-validator=MIT license validator variant
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists