blob: 6fcbb7cbc0b6a5144e2d3d90693ee91744f85524 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* 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.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.literals;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteralContainer;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* @author ilyas
*/
public class GrLiteralImpl extends GrAbstractLiteral implements GrLiteral, PsiLanguageInjectionHost {
private static final Logger LOG = Logger.getInstance(GrLiteralImpl.class);
public GrLiteralImpl(@NotNull ASTNode node) {
super(node);
}
public String toString() {
return "Literal";
}
@Override
public PsiType getType() {
IElementType elemType = getLiteralType(this);
return TypesUtil.getPsiType(this, elemType);
}
@Override
public void accept(GroovyElementVisitor visitor) {
visitor.visitLiteralExpression(this);
}
@Override
public Object getValue() {
return getLiteralValue(getFirstChild());
}
public static Object getLiteralValue(PsiElement child) {
IElementType elemType = child.getNode().getElementType();
String text = child.getText();
if (TokenSets.NUMBERS.contains(elemType)) {
text = text.replaceAll("_", "");
try {
if (elemType == GroovyTokenTypes.mNUM_INT) {
return Integer.parseInt(text);
}
else if (elemType == GroovyTokenTypes.mNUM_LONG) {
return Long.parseLong(text);
}
else if (elemType == GroovyTokenTypes.mNUM_FLOAT) {
return Float.parseFloat(text);
}
else if (elemType == GroovyTokenTypes.mNUM_DOUBLE) {
return Double.parseDouble(text);
}
else if (elemType == GroovyTokenTypes.mNUM_BIG_INT) {
return new BigInteger(text);
}
else if (elemType == GroovyTokenTypes.mNUM_BIG_DECIMAL) {
return new BigDecimal(text);
}
}
catch (NumberFormatException ignored) {
}
}
else if (elemType == GroovyTokenTypes.kFALSE) {
return Boolean.FALSE;
}
else if (elemType == GroovyTokenTypes.kTRUE) {
return Boolean.TRUE;
}
else if (elemType == GroovyTokenTypes.mSTRING_LITERAL) {
if (!text.startsWith("'")) return null;
text = GrStringUtil.removeQuotes(text);
StringBuilder chars = new StringBuilder(text.length());
boolean result = GrStringUtil.parseStringCharacters(text, chars, null);
return result ? chars.toString() : null;
}
else if (elemType == GroovyTokenTypes.mGSTRING_LITERAL) {
if (!text.startsWith("\"")) return null;
text = GrStringUtil.removeQuotes(text);
StringBuilder chars = new StringBuilder(text.length());
boolean result = GrStringUtil.parseStringCharacters(text, chars, null);
return result ? chars.toString() : null;
}
else if (elemType == GroovyTokenTypes.mREGEX_LITERAL) {
final PsiElement cchild = child.getFirstChild();
if (cchild == null) return null;
final PsiElement sibling = cchild.getNextSibling();
if (sibling == null) return null;
text = sibling.getText();
final StringBuilder chars = new StringBuilder(text.length());
boolean result = GrStringUtil.parseRegexCharacters(text, chars, null, true);
return result ? chars.toString() : null;
}
else if (elemType == GroovyTokenTypes.mDOLLAR_SLASH_REGEX_LITERAL) {
final PsiElement cchild = child.getFirstChild();
if (cchild == null) return null;
final PsiElement sibling = cchild.getNextSibling();
if (sibling == null) return null;
text = sibling.getText();
final StringBuilder chars = new StringBuilder(text.length());
boolean result = GrStringUtil.parseRegexCharacters(text, chars, null, false);
return result ? chars.toString() : null;
}
return null;
}
public static IElementType getLiteralType(GrLiteral literal) {
PsiElement firstChild = literal.getFirstChild();
assert firstChild != null;
return firstChild.getNode().getElementType();
}
public boolean isStringLiteral() {
PsiElement child = getFirstChild();
if (child == null) return false;
IElementType elementType = child.getNode().getElementType();
return TokenSets.STRING_LITERAL_SET.contains(elementType);
}
@Override
@NotNull
public PsiReference[] getReferences() {
return ReferenceProvidersRegistry.getReferencesFromProviders(this, PsiReferenceService.Hints.NO_HINTS);
}
@Nullable
@Override
public PsiReference getReference() {
final PsiReference[] references = getReferences();
if (references.length == 1) {
return references[0];
}
if (references.length > 1) {
return new PsiMultiReference(references, this);
}
return null;
}
@Override
public boolean isValidHost() {
return getValue() instanceof String;
}
@Override
public GrLiteralImpl updateText(@NotNull final String text) {
final GrExpression newExpr = GroovyPsiElementFactory.getInstance(getProject()).createExpressionFromText(text);
LOG.assertTrue(newExpr instanceof GrLiteral, text);
LOG.assertTrue(newExpr.getFirstChild() != null, text);
final ASTNode valueNode = getNode().getFirstChildNode();
getNode().replaceChild(valueNode, newExpr.getFirstChild().getNode());
return this;
}
@Override
@NotNull
public LiteralTextEscaper<GrLiteralContainer> createLiteralTextEscaper() {
return new GrLiteralEscaper(this);
}
}