/* * Copyright 2013 Guidewire Software, Inc. */ package gw.plugin.ij.lang.psi.impl.expressions; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiJavaToken; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiNamedElement; import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; import com.intellij.psi.impl.source.tree.CompositePsiElement; import com.intellij.psi.tree.IElementType; import com.intellij.util.IncorrectOperationException; import gw.plugin.ij.lang.GosuTokenTypes; import gw.plugin.ij.lang.psi.IGosuFile; import gw.plugin.ij.lang.psi.api.expressions.IGosuIdentifier; import gw.plugin.ij.lang.psi.api.statements.typedef.IGosuTypeDefinition; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class LightGosuIdentifierImpl extends CompositePsiElement implements PsiJavaToken, PsiNamedElement, IGosuIdentifier { private CharSequence _text; public LightGosuIdentifierImpl(CharSequence text) { super(GosuTokenTypes.TT_IDENTIFIER); _text = text; } @NotNull @Override public CompositePsiElement clone() { return new LightGosuIdentifierImpl(_text.toString()); } @NotNull public IElementType getTokenType() { return GosuTokenTypes.TT_IDENTIFIER; } public void accept(@NotNull PsiElementVisitor visitor) { visitor.visitElement(this); } @Override public PsiElement replace(@NotNull PsiElement newElement) throws IncorrectOperationException { PsiElement result = super.replace(newElement); // We want to reformat method parameters on method name change as well because there is a possible situation that they are aligned // and method name change breaks the alignment. // Example: // public void test(int i, // int j) {} // Suppose we're renaming the method to test123. We get the following if parameter list is not reformatted: // public void test123(int i, // int j) {} PsiElement methodCandidate = result.getParent(); if (methodCandidate instanceof PsiMethod) { PsiMethod method = (PsiMethod) methodCandidate; CodeEditUtil.markToReformat(method.getParameterList().getNode(), true); } return result; } @NotNull public String toString() { return "PsiIdentifier: " + getText(); } @Override public String getName() { return _text.toString(); } @NotNull public PsiElement setName(@NonNls @NotNull String newName) throws IncorrectOperationException { PsiFile fileToRename = getFileToRenameIfRenamingType(); PsiElement me = renameJustMe(newName); if (fileToRename != null) { renameMyTypesFile(newName, fileToRename); } return me; } @NotNull private PsiElement renameJustMe(String name) { LightGosuIdentifierImpl elem = (LightGosuIdentifierImpl) copy(); elem._text = name; replace(elem); return elem; } private void renameMyTypesFile(String newName, @NotNull PsiFile fileToRename) { String fileName = fileToRename.getName(); int dotIndex = fileName.lastIndexOf('.'); fileToRename.setName(dotIndex >= 0 ? newName + "." + fileName.substring(dotIndex + 1) : newName); } @Nullable private PsiFile getFileToRenameIfRenamingType() { if (getParent() instanceof IGosuTypeDefinition) { IGosuTypeDefinition typeDef = (IGosuTypeDefinition) getParent(); if (typeDef.getParent() instanceof PsiFile) { PsiFile file = typeDef.getContainingFile(); if (!(file instanceof IGosuFile)) { return null; } final IGosuFile gosuFile = (IGosuFile) file; final String name = getName(); final VirtualFile vFile = gosuFile.getVirtualFile(); return vFile != null && name != null && name.equals(vFile.getNameWithoutExtension()) ? file : null; } } return null; } }