blob: e0c09866c81399700a3b4f8949357770ea8997ab [file] [log] [blame]
/*
* Copyright 2000-2013 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 com.intellij.psi.impl.cache;
import com.intellij.lang.LighterAST;
import com.intellij.lang.LighterASTNode;
import com.intellij.lang.LighterASTTokenNode;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiModifierList;
import com.intellij.psi.impl.java.stubs.*;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.impl.source.tree.LightTreeUtil;
import com.intellij.psi.stubs.PsiFileStub;
import com.intellij.psi.stubs.StubElement;
import com.intellij.util.CharTable;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @author max
*/
public class RecordUtil {
@NonNls private static final String DEPRECATED_ANNOTATION_NAME = "Deprecated";
@NonNls private static final String DEPRECATED_TAG = "@deprecated";
private RecordUtil() { }
public static boolean isDeprecatedByAnnotation(@NotNull LighterAST tree, @NotNull LighterASTNode modList) {
for (final LighterASTNode child : tree.getChildren(modList)) {
if (child.getTokenType() == JavaElementType.ANNOTATION) {
final LighterASTNode ref = LightTreeUtil.firstChildOfType(tree, child, JavaElementType.JAVA_CODE_REFERENCE);
if (ref != null) {
final LighterASTNode id = LightTreeUtil.firstChildOfType(tree, ref, JavaTokenType.IDENTIFIER);
if (id != null) {
final String name = intern(tree.getCharTable(), id);
if (DEPRECATED_ANNOTATION_NAME.equals(name)) return true;
}
}
}
}
return false;
}
public static boolean isDeprecatedByDocComment(@NotNull LighterAST tree, @NotNull LighterASTNode comment) {
// todo[r.sh] parse doc comments, implement tree lookup
String text = LightTreeUtil.toFilteredString(tree, comment, null);
return text.contains(DEPRECATED_TAG);
}
public static int packModifierList(@NotNull LighterAST tree, @NotNull LighterASTNode modList, @NotNull StubElement parent) {
int packed = 0;
final LighterASTNode modListOwner = tree.getParent(modList);
if (modListOwner != null && modListOwner.getTokenType() == parent.getStubType()) {
final StubElement grandParent = parent.getParentStub();
if (parent instanceof PsiClassStub) {
if (grandParent instanceof PsiClassStub && ((PsiClassStub)grandParent).isInterface()) {
packed |= ModifierFlags.PUBLIC_MASK;
packed |= ModifierFlags.STATIC_MASK;
}
if (((PsiClassStub)parent).isInterface()) {
packed |= ModifierFlags.ABSTRACT_MASK;
if (grandParent instanceof PsiClassStub) {
packed |= ModifierFlags.STATIC_MASK;
}
}
else if (((PsiClassStub)parent).isEnum()) {
if (!(grandParent instanceof PsiFileStub)) {
packed |= ModifierFlags.STATIC_MASK;
}
boolean isFinal = true;
final List<LighterASTNode> enumConstants = LightTreeUtil.getChildrenOfType(tree, modListOwner, JavaElementType.ENUM_CONSTANT);
for (final LighterASTNode constant : enumConstants) {
if (LightTreeUtil.firstChildOfType(tree, constant, JavaElementType.ENUM_CONSTANT_INITIALIZER) != null) {
isFinal = false;
break;
}
}
if (isFinal) {
packed |= ModifierFlags.FINAL_MASK;
}
final List<LighterASTNode> methods = LightTreeUtil.getChildrenOfType(tree, modListOwner, JavaElementType.METHOD);
for (final LighterASTNode method : methods) {
final LighterASTNode mods = LightTreeUtil.requiredChildOfType(tree, method, JavaElementType.MODIFIER_LIST);
if (LightTreeUtil.firstChildOfType(tree, mods, JavaTokenType.ABSTRACT_KEYWORD) != null) {
packed |= ModifierFlags.ABSTRACT_MASK;
break;
}
}
}
}
else if (parent instanceof PsiMethodStub) {
if (grandParent instanceof PsiClassStub && ((PsiClassStub)grandParent).isInterface()) {
packed |= ModifierFlags.PUBLIC_MASK;
packed |= ModifierFlags.ABSTRACT_MASK;
}
}
else if (parent instanceof PsiFieldStub) {
if (parent.getStubType() == JavaElementType.ENUM_CONSTANT ||
grandParent instanceof PsiClassStub && ((PsiClassStub)grandParent).isInterface()) {
packed |= ModifierFlags.PUBLIC_MASK;
packed |= ModifierFlags.STATIC_MASK;
packed |= ModifierFlags.FINAL_MASK;
}
}
}
for (final LighterASTNode child : tree.getChildren(modList)) {
final int flag = ModifierFlags.KEYWORD_TO_MODIFIER_FLAG_MAP.get(child.getTokenType());
if (flag != 0) {
packed |= flag;
}
}
if ((packed & ModifierFlags.DEFENDER_MASK) != 0) {
packed &= ~ModifierFlags.ABSTRACT_MASK;
}
if ((packed & (ModifierFlags.PRIVATE_MASK | ModifierFlags.PROTECTED_MASK | ModifierFlags.PUBLIC_MASK)) == 0) {
packed |= ModifierFlags.PACKAGE_LOCAL_MASK;
}
return packed;
}
@NotNull
public static String intern(@NotNull CharTable table, @NotNull LighterASTNode node) {
assert node instanceof LighterASTTokenNode : node;
return table.intern(((LighterASTTokenNode)node).getText()).toString();
}
public static boolean isStaticNonPrivateMember(@NotNull StubElement<?> stub) {
StubElement<PsiModifierList> type = stub.findChildStubByType(JavaStubElementTypes.MODIFIER_LIST);
if (!(type instanceof PsiModifierListStub)) {
return false;
}
int mask = ((PsiModifierListStub)type).getModifiersMask();
return ModifierFlags.hasModifierProperty(PsiModifier.STATIC, mask) && !ModifierFlags.hasModifierProperty(PsiModifier.PRIVATE, mask);
}
}