package jetbrains.mps.idea.java.psiStubs;
/*Generated by MPS */
import jetbrains.mps.idea.core.refactoring.NodePtr;
import com.intellij.psi.PsiElement;
import jetbrains.mps.smodel.SNodeId;
import org.jetbrains.mps.openapi.model.SModelReference;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import org.jetbrains.mps.openapi.module.SModule;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import jetbrains.mps.idea.core.facet.MPSFacet;
import com.intellij.facet.FacetManager;
import jetbrains.mps.idea.core.facet.MPSFacetType;
import com.intellij.util.xml.ModuleContentRootSearchScope;
import jetbrains.mps.java.stub.JavaPackageNameStub;
import jetbrains.mps.smodel.SModelId;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiTypeElement;
import com.intellij.psi.PsiType;
public class JavaForeignIdBuilder {
public static NodePtr computeNodePtr(PsiElement element) {
SNodeId nodeId = computeNodeId(element);
SModelReference modelRef = computeModelReference(element);
if (nodeId == null || modelRef == null) {
return null;
}
return new NodePtr(modelRef, nodeId);
}
@Nullable
public static SNodeId.Foreign computeNodeId(@NotNull PsiElement element) {
PsiElement parent = element.getParent();
String prefix;
if (parent instanceof PsiFile) {
// element is root
prefix = SNodeId.Foreign.ID_PREFIX;
} else {
org.jetbrains.mps.openapi.model.SNodeId parentId = computeNodeId(parent);
if (parentId == null) {
return null;
}
prefix = parentId.toString() + ".";
}
// e.g. this was an anonymous class and we don't compute nodeId for parent
if (prefix == null) {
return null;
}
return computeNodeId(prefix, element);
}
@Nullable
public static SModelReference computeModelReference(PsiElement element) {
PsiFile file = element.getContainingFile();
if (!(file instanceof PsiJavaFile)) {
return null;
}
String packageName = ((PsiJavaFile) file).getPackageName();
// we want to know mps module id
SModule mpsModule = null;
Project project = element.getProject();
VirtualFile vfile = file.getVirtualFile();
// MPS-17704: there was situation when an element with null virtual file came from MPSReferenceSearch
// element was the target of search
if (vfile == null) {
return null;
}
for (Module module : ModuleManager.getInstance(project).getModules()) {
MPSFacet facet = FacetManager.getInstance(module).getFacetByType(MPSFacetType.ID);
if (facet == null) {
continue;
}
if (new ModuleContentRootSearchScope(module).contains(vfile)) {
mpsModule = facet.getSolution();
break;
}
}
if (mpsModule == null) {
return null;
}
return new JavaPackageNameStub(packageName).asModelReference(mpsModule.getModuleReference());
}
/*package*/ static jetbrains.mps.smodel.SModelReference computeModelReference(String packageName, String mpsModuleId) {
String stereotype = "java_stub";
if (packageName.length() == 0) {
packageName = "<default package>";
}
SModelId modelId = SModelId.foreign(stereotype, packageName);
return new jetbrains.mps.smodel.SModelReference(null, modelId, packageName + "@" + stereotype);
}
/*package*/ static SNodeId.Foreign computeNodeId(String prefix, PsiElement element) {
StringBuilder sb = new StringBuilder(prefix);
if (element instanceof PsiClass || element instanceof PsiField) {
// simply take the name
String name = ((PsiNamedElement) element).getName();
if (name == null) {
return null;
}
sb.append(name);
} else if (element instanceof PsiMethod) {
PsiMethod method = (PsiMethod) element;
String name = method.getName();
if (name == null) {
return null;
}
if (((PsiMethod) element).isConstructor()) {
sb.deleteCharAt(sb.length() - 1);
} else {
sb.append(name);
}
sb.append('(');
for (PsiParameter param : method.getParameterList().getParameters()) {
// for classess we want their name exactly how it is written in the source file
// (either short name, partially qualified or fully qualified)
// to make it equal to what we have in eclipse stubs
PsiTypeElement psiTypeElem = param.getTypeElement();
PsiType psiType = param.getType();
if (psiType != null && psiTypeElem != null) {
sb.append(ASTConverter.typeReferenceId(psiTypeElem));
sb.append(',');
}
}
int last = sb.length() - 1;
if (sb.charAt(last) == ',') {
sb.deleteCharAt(last);
}
sb.append(')');
}
return new SNodeId.Foreign(sb.toString());
}
}