blob: 5c97ac35489b97b21af106b83ef29e70f27adf77 [file] [log] [blame]
/*
* Copyright 2006 Sascha Weinreuter
*
* Licensed 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.intellij.lang.regexp.psi.impl;
import com.intellij.codeInsight.lookup.LookupValueFactory;
import com.intellij.codeInsight.lookup.LookupValueWithPriority;
import com.intellij.codeInsight.lookup.LookupValueWithUIHint;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PlatformIcons;
import org.intellij.lang.regexp.RegExpLanguageHosts;
import org.intellij.lang.regexp.RegExpTT;
import org.intellij.lang.regexp.psi.RegExpElementVisitor;
import org.intellij.lang.regexp.psi.RegExpProperty;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
public class RegExpPropertyImpl extends RegExpElementImpl implements RegExpProperty {
public RegExpPropertyImpl(ASTNode astNode) {
super(astNode);
}
public PsiReference getReference() {
final ASTNode lbrace = getNode().findChildByType(RegExpTT.LBRACE);
if (lbrace == null) return null;
return new MyPsiReference();
}
public boolean isNegated() {
final ASTNode node = getNode().findChildByType(RegExpTT.PROPERTY);
return node != null && node.textContains('P');
}
@Nullable
public ASTNode getCategoryNode() {
return getNode().findChildByType(RegExpTT.NAME);
}
public void accept(RegExpElementVisitor visitor) {
visitor.visitRegExpProperty(this);
}
private class MyPsiReference implements PsiReference {
public PsiElement getElement() {
return RegExpPropertyImpl.this;
}
public TextRange getRangeInElement() {
final ASTNode lbrace = getNode().findChildByType(RegExpTT.LBRACE);
assert lbrace != null;
final ASTNode rbrace = getNode().findChildByType(RegExpTT.RBRACE);
int to = rbrace == null ? getTextRange().getEndOffset() : rbrace.getTextRange().getEndOffset() - 1;
final TextRange t = new TextRange(lbrace.getStartOffset() + 1, to);
return t.shiftRight(-getTextRange().getStartOffset());
}
@Nullable
public PsiElement resolve() {
return RegExpPropertyImpl.this;
}
@NotNull
public String getCanonicalText() {
return getRangeInElement().substring(getElement().getText());
}
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
throw new IncorrectOperationException();
}
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
throw new IncorrectOperationException();
}
public boolean isReferenceTo(PsiElement element) {
return false;
}
@NotNull
public Object[] getVariants() {
final ASTNode categoryNode = getCategoryNode();
if (categoryNode != null && categoryNode.getText().startsWith("In") && !categoryNode.getText().startsWith("Intelli")) {
return UNICODE_BLOCKS;
} else {
final String[][] knownProperties = RegExpLanguageHosts.getInstance().getAllKnownProperties(getElement());
final Object[] objects = new Object[knownProperties.length];
for (int i = 0; i < objects.length; i++) {
final String[] prop = knownProperties[i];
objects[i] = new MyLookupValue(prop);
}
return objects;
}
}
public boolean isSoft() {
return true;
}
private class MyLookupValue extends LookupValueFactory.LookupValueWithIcon implements LookupValueWithPriority, LookupValueWithUIHint {
private final String[] myProp;
public MyLookupValue(String[] prop) {
super(prop[0], PlatformIcons.PROPERTY_ICON);
myProp = prop;
}
public String getPresentation() {
final ASTNode categoryNode = getCategoryNode();
if (categoryNode != null) {
if (categoryNode.getText().startsWith("Is")) {
return "Is" + super.getPresentation();
}
}
return super.getPresentation();
}
public int getPriority() {
final String name = myProp[0];
if (name.equals("all")) return HIGH + 1;
if (name.startsWith("java")) return HIGHER;
return name.length() > 2 ? HIGH : NORMAL;
}
public String getTypeHint() {
return myProp.length > 1 ? myProp[1] : ("Character.is" + myProp[0].substring("java".length()) + "()");
}
@Nullable
public Color getColorHint() {
return null;
}
public boolean isBold() {
return false;
}
}
}
private static final String[] UNICODE_BLOCKS;
static {
final Field[] fields = Character.UnicodeBlock.class.getFields();
final List<String> unicodeBlocks = new ArrayList<String>(fields.length);
for (Field field : fields) {
if (field.getType().equals(Character.UnicodeBlock.class)) {
if (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers())) {
unicodeBlocks.add("In" + field.getName());
}
}
}
UNICODE_BLOCKS = ArrayUtil.toStringArray(unicodeBlocks);
}
}