org.netbeans.editor.TokenContext Maven / Gradle / Ivy
/*
* 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.editor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Arrays;
import java.util.ArrayList;
/**
* Token context defines the environment in which only a limited set
* of tokens can be used. This set can be retrieved by calling
* the getTokenIDs() method. The context can contain other
* contexts which means that the context can possibly switch
* into one of its children contexts during lexing.
* The child context can also have other children that can
* work in the same way.
* In this way context-paths can be created. They describe
* the way how was the token lexically recognized.
* The context can be retrieved when the syntax-class is known
* using the get method.
*
*
* @author Miloslav Metelka
* @version 1.00
*/
public class TokenContext {
private static final TokenContext[] EMPTY_CHILDREN = new TokenContext[0];
private final String namePrefix;
private final TokenContext[] children;
private final HashMap pathCache = new HashMap(37);
private final ArrayList tokenIDList = new ArrayList();
private final ArrayList tokenCategoryList = new ArrayList();
private TokenID[] tokenIDs;
private TokenCategory[] tokenCategories;
private TokenContextPath contextPath;
private TokenContextPath[] allContextPaths;
private TokenContextPath[] lastContextPathPair;
public TokenContext(String namePrefix) {
this(namePrefix, EMPTY_CHILDREN);
}
/** Construct new token-context.
* @param namePrefix name that will prefix all the token-ids names.
* @param children child token contexts.
*/
public TokenContext(String namePrefix, TokenContext[] children) {
if (namePrefix == null) {
throw new IllegalArgumentException("Name prefix must be non-null."); // NOI18N
}
this.namePrefix = namePrefix.intern();
this.children = (children != null) ? children : EMPTY_CHILDREN;
contextPath = TokenContextPath.get(new TokenContext[] { this });
}
/** Get the prefix that this context adds to the name of its tokens. */
public String getNamePrefix() {
return namePrefix;
}
/** Get the children contexts of this context. It returns empty-array
* if there are no children.
*/
public TokenContext[] getChildren() {
return children;
}
/** Add token-id to the set of token-ids that belong to this context. */
protected void addTokenID(TokenID tokenID) {
synchronized (tokenIDList) {
tokenIDList.add(tokenID);
tokenIDs = null;
// Check whether there's a valid and new category for this token-id
TokenCategory tcat = tokenID.getCategory();
if (tcat != null && tokenCategoryList.indexOf(tcat) < 0) {
tokenCategoryList.add(tcat);
tokenCategories = null;
}
}
}
/** Add all static-final token-id fields declared
* in this token-context using Class.getDeclaredFields() call.
*/
protected void addDeclaredTokenIDs() throws IllegalAccessException, SecurityException {
Field[] fields = this.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
int flags = Modifier.STATIC | Modifier.FINAL;
if ((fields[i].getModifiers() & flags) == flags
&& TokenID.class.isAssignableFrom(fields[i].getType())
) {
addTokenID((TokenID)fields[i].get(null));
}
}
}
/** Get the token-ids that belong to this token-context. It doesn't
* return the children's token-ids.
*/
public TokenID[] getTokenIDs() {
if (tokenIDs == null) {
synchronized (tokenIDList) {
tokenIDs = (TokenID[])tokenIDList.toArray(new TokenID[tokenIDList.size()]);
}
}
return tokenIDs;
}
/** Get the token-categories that belong to this token-context. It doesn't
* return the children's token-categories.
*/
public TokenCategory[] getTokenCategories() {
if (tokenCategories == null) {
synchronized (tokenCategoryList) {
tokenCategories = (TokenCategory[])tokenCategoryList.toArray(
new TokenCategory[tokenCategoryList.size()]);
}
}
return tokenCategories;
}
/** Get the context path for this token-context. */
public TokenContextPath getContextPath() {
return contextPath;
}
/** Get the context path for this token-context that is derived
* from the path of one of the children.
*/
public TokenContextPath getContextPath(TokenContextPath childPath) {
if (childPath == null) {
return contextPath;
}
TokenContextPath[] lastPair = lastContextPathPair;
if (lastPair == null || lastPair[0] != childPath) {
synchronized (pathCache) {
lastPair = (TokenContextPath[])pathCache.get(childPath);
if (lastPair == null) {
// Build the array of contexts
TokenContext[] origContexts = childPath.getContexts();
TokenContext[] contexts = new TokenContext[origContexts.length + 1];
System.arraycopy(origContexts, 0, contexts, 0, origContexts.length);
contexts[origContexts.length] = this;
TokenContextPath path = TokenContextPath.get(contexts);
lastPair = new TokenContextPath[] { childPath, path };
pathCache.put(childPath, lastPair);
}
lastContextPathPair = lastPair;
}
}
return lastPair[1];
}
/** Get all the context paths for this token-context including
* itself as the first one and all its children.
*/
public TokenContextPath[] getAllContextPaths() {
synchronized (tokenIDList) {
if (allContextPaths == null) {
ArrayList cpList = new ArrayList();
cpList.add(getContextPath());
for (int i = 0; i < children.length; i++) {
TokenContextPath[] childPaths = children[i].getAllContextPaths();
for (int j = 0; j < childPaths.length; j++) {
cpList.add(getContextPath(childPaths[j]));
}
}
allContextPaths = new TokenContextPath[cpList.size()];
cpList.toArray(allContextPaths);
}
return allContextPaths;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy