/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.plugin.ij.lang.psi.stubs.elements;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.PsiModifierList;
import com.intellij.psi.PsiModifierListOwner;
import com.intellij.psi.PsiNameHelper;
import com.intellij.psi.impl.java.stubs.index.JavaFullClassNameIndex;
import com.intellij.psi.impl.java.stubs.index.JavaShortClassNameIndex;
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.util.ArrayUtil;
import com.intellij.util.containers.CollectionFactory;
import com.intellij.util.io.StringRef;
import gw.lang.parser.IParsedElement;
import gw.plugin.ij.lang.psi.GosuStubElementType;
import gw.plugin.ij.lang.psi.api.auxilary.IGosuModifierList;
import gw.plugin.ij.lang.psi.api.auxilary.annotation.IGosuAnnotation;
import gw.plugin.ij.lang.psi.api.statements.typedef.IGosuTypeDefinition;
import gw.plugin.ij.lang.psi.stubs.GosuTypeDefinitionStub;
import gw.plugin.ij.lang.psi.stubs.impl.GosuTypeDefinitionStubImpl;
import gw.plugin.ij.lang.psi.stubs.index.GosuAnnotatedMemberIndex;
import gw.plugin.ij.lang.psi.stubs.index.GosuAnonymousClassIndex;
import gw.plugin.ij.lang.psi.stubs.index.GosuShortClassNameIndex;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.List;
public abstract class GosuTypeDefinitionElementType<TypeDef extends IGosuTypeDefinition>
extends GosuStubElementType<GosuTypeDefinitionStub, TypeDef> {
public GosuTypeDefinitionElementType(@NotNull String debugName, Class<? extends IParsedElement> peType) {
super(debugName, peType);
}
@NotNull
public GosuTypeDefinitionStub createStub(@NotNull TypeDef psi, StubElement parentStub) {
String[] superClassNames = psi.getSuperClassNames();
final byte flags = GosuTypeDefinitionStubImpl.buildFlags(psi);
return new GosuTypeDefinitionStubImpl(parentStub, psi.getName(), superClassNames, this, psi.getQualifiedName(), getAnnotationNames(psi),
flags);
}
@NotNull
public static String[] getAnnotationNames(@NotNull PsiModifierListOwner psi) {
List<String> annoNames = CollectionFactory.arrayList();
final PsiModifierList modifierList = psi.getModifierList();
if (modifierList instanceof IGosuModifierList) {
for (IGosuAnnotation annotation : ((IGosuModifierList) modifierList).getAnnotations()) {
final PsiJavaCodeReferenceElement element = annotation.getClassReference();
if (element != null) {
final String annoShortName = StringUtil.getShortName(element.getText()).trim();
if (StringUtil.isNotEmpty(annoShortName)) {
annoNames.add(annoShortName);
}
}
}
}
return ArrayUtil.toStringArray(annoNames);
}
public void serialize(@NotNull GosuTypeDefinitionStub stub, @NotNull StubOutputStream dataStream) throws IOException {
dataStream.writeName(stub.getName());
dataStream.writeName(stub.getQualifiedName());
dataStream.writeByte(stub.getFlags());
writeStringArray(dataStream, stub.getSuperClassNames());
writeStringArray(dataStream, stub.getAnnotations());
}
private static void writeStringArray(@NotNull StubOutputStream dataStream, @NotNull String[] names) throws IOException {
dataStream.writeByte(names.length);
for (String name : names) {
dataStream.writeName(name);
}
}
@NotNull
public GosuTypeDefinitionStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
String name = StringRef.toString(dataStream.readName());
String qname = StringRef.toString(dataStream.readName());
byte flags = dataStream.readByte();
String[] superClasses = readStringArray(dataStream);
String[] annos = readStringArray(dataStream);
return new GosuTypeDefinitionStubImpl(parentStub, name, superClasses, this, qname, annos, flags);
}
@NotNull
private static String[] readStringArray(@NotNull StubInputStream dataStream) throws IOException {
byte supersNumber = dataStream.readByte();
String[] superClasses = new String[supersNumber];
for (int i = 0; i < supersNumber; i++) {
superClasses[i] = StringRef.toString(dataStream.readName());
}
return superClasses;
}
public void indexStub(@NotNull GosuTypeDefinitionStub stub, @NotNull IndexSink sink) {
if (stub.isAnonymous()) {
final String[] classNames = stub.getSuperClassNames();
if (classNames.length != 1) {
return;
}
final String baseClassName = classNames[0];
if (baseClassName != null) {
final String shortName = PsiNameHelper.getShortClassName(baseClassName);
sink.occurrence(GosuAnonymousClassIndex.KEY, shortName);
}
} else {
String shortName = stub.getName();
if (shortName != null) {
sink.occurrence(JavaShortClassNameIndex.getInstance().getKey(), shortName);
sink.occurrence(GosuShortClassNameIndex.KEY, shortName);
}
final String fqn = stub.getQualifiedName();
if (fqn != null) {
sink.occurrence(JavaFullClassNameIndex.getInstance().getKey(), fqn.hashCode());
}
}
for (String annName : stub.getAnnotations()) {
if (annName != null) {
sink.occurrence(GosuAnnotatedMemberIndex.KEY, annName);
}
}
}
}