/* * 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.java.stubs; import com.intellij.lang.ASTNode; import com.intellij.lang.LighterAST; import com.intellij.lang.LighterASTNode; import com.intellij.psi.JavaTokenType; import com.intellij.psi.PsiMethod; import com.intellij.psi.impl.cache.RecordUtil; import com.intellij.psi.impl.cache.TypeInfo; import com.intellij.psi.impl.java.stubs.impl.PsiMethodStubImpl; import com.intellij.psi.impl.java.stubs.index.JavaStubIndexKeys; import com.intellij.psi.impl.source.PsiAnnotationMethodImpl; import com.intellij.psi.impl.source.PsiMethodImpl; import com.intellij.psi.impl.source.tree.ElementType; import com.intellij.psi.impl.source.tree.JavaDocElementType; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.impl.source.tree.LightTreeUtil; import com.intellij.psi.impl.source.tree.java.AnnotationMethodElement; import com.intellij.psi.stubs.IndexSink; import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubInputStream; import com.intellij.psi.stubs.StubOutputStream; import com.intellij.psi.tree.IElementType; import com.intellij.util.io.StringRef; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.util.List; /** * @author max */ public abstract class JavaMethodElementType extends JavaStubElementType<PsiMethodStub, PsiMethod> { public JavaMethodElementType(@NonNls final String name) { super(name); } @Override public PsiMethod createPsi(@NotNull final PsiMethodStub stub) { return getPsiFactory(stub).createMethod(stub); } @Override public PsiMethod createPsi(@NotNull final ASTNode node) { if (node instanceof AnnotationMethodElement) { return new PsiAnnotationMethodImpl(node); } else { return new PsiMethodImpl(node); } } @Override public PsiMethodStub createStub(final LighterAST tree, final LighterASTNode node, final StubElement parentStub) { String name = null; boolean isConstructor = true; boolean isVarArgs = false; boolean isDeprecatedByComment = false; boolean hasDeprecatedAnnotation = false; String defValueText = null; boolean expectingDef = false; for (final LighterASTNode child : tree.getChildren(node)) { final IElementType type = child.getTokenType(); if (type == JavaDocElementType.DOC_COMMENT) { isDeprecatedByComment = RecordUtil.isDeprecatedByDocComment(tree, child); } else if (type == JavaElementType.MODIFIER_LIST) { hasDeprecatedAnnotation = RecordUtil.isDeprecatedByAnnotation(tree, child); } else if (type == JavaElementType.TYPE) { isConstructor = false; } else if (type == JavaTokenType.IDENTIFIER) { name = RecordUtil.intern(tree.getCharTable(), child); } else if (type == JavaElementType.PARAMETER_LIST) { final List<LighterASTNode> params = LightTreeUtil.getChildrenOfType(tree, child, JavaElementType.PARAMETER); if (params.size() > 0) { final LighterASTNode pType = LightTreeUtil.firstChildOfType(tree, params.get(params.size() - 1), JavaElementType.TYPE); if (pType != null) { isVarArgs = (LightTreeUtil.firstChildOfType(tree, pType, JavaTokenType.ELLIPSIS) != null); } } } else if (type == JavaTokenType.DEFAULT_KEYWORD) { expectingDef = true; } else if (expectingDef && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(type) && type != JavaTokenType.SEMICOLON && type != JavaElementType.CODE_BLOCK) { defValueText = LightTreeUtil.toFilteredString(tree, child, null); break; } } TypeInfo typeInfo = isConstructor ? TypeInfo.createConstructorType() : TypeInfo.create(tree, node, parentStub); boolean isAnno = (node.getTokenType() == JavaElementType.ANNOTATION_METHOD); byte flags = PsiMethodStubImpl.packFlags(isConstructor, isAnno, isVarArgs, isDeprecatedByComment, hasDeprecatedAnnotation); return new PsiMethodStubImpl(parentStub, StringRef.fromString(name), typeInfo, flags, StringRef.fromString(defValueText)); } @Override public void serialize(@NotNull final PsiMethodStub stub, @NotNull final StubOutputStream dataStream) throws IOException { dataStream.writeName(stub.getName()); TypeInfo.writeTYPE(dataStream, stub.getReturnTypeText(false)); dataStream.writeByte(((PsiMethodStubImpl)stub).getFlags()); if (stub.isAnnotationMethod()) { dataStream.writeName(stub.getDefaultValueText()); } } @NotNull @Override public PsiMethodStub deserialize(@NotNull final StubInputStream dataStream, final StubElement parentStub) throws IOException { StringRef name = dataStream.readName(); final TypeInfo type = TypeInfo.readTYPE(dataStream); byte flags = dataStream.readByte(); final StringRef defaultMethodValue = PsiMethodStubImpl.isAnnotationMethod(flags) ? dataStream.readName() : null; return new PsiMethodStubImpl(parentStub, name, type, flags, defaultMethodValue); } @Override public void indexStub(@NotNull final PsiMethodStub stub, @NotNull final IndexSink sink) { final String name = stub.getName(); if (name != null) { sink.occurrence(JavaStubIndexKeys.METHODS, name); if (RecordUtil.isStaticNonPrivateMember(stub)) { sink.occurrence(JavaStubIndexKeys.JVM_STATIC_MEMBERS_NAMES, name); sink.occurrence(JavaStubIndexKeys.JVM_STATIC_MEMBERS_TYPES, stub.getReturnTypeText(false).getShortTypeText()); } } } }