/* * 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.PsiMember; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiReference; import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; import com.intellij.psi.impl.source.tree.LeafPsiElement; 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 gw.plugin.ij.lang.psi.impl.GosuElementVisitor; import gw.plugin.ij.lang.psi.impl.statements.GosuFieldImpl; import gw.plugin.ij.lang.psi.impl.statements.GosuVariableImpl; import gw.plugin.ij.lang.psi.impl.statements.typedef.members.GosuMethodBaseImpl; import gw.plugin.ij.lang.psi.util.GosuPsiParseUtil; import gw.plugin.ij.util.InjectedElementEditor; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class GosuIdentifierImpl extends LeafPsiElement implements PsiJavaToken, IGosuIdentifier { public GosuIdentifierImpl(IElementType tokType, CharSequence text) { super(tokType, text); } @NotNull public IElementType getTokenType() { return GosuTokenTypes.TT_IDENTIFIER; } @Override public void accept(@NotNull PsiElementVisitor visitor) { if( visitor instanceof GosuElementVisitor) { ((GosuElementVisitor)visitor).visitIdentifier(this); } else { visitor.visitElement( this ); } } public PsiReference getReference() { if (InjectedElementEditor.isInEmbeddedEditor(this) && ( getParent() instanceof GosuFieldImpl || getParent() instanceof GosuVariableImpl || getParent() instanceof GosuMethodBaseImpl)) { final PsiElement originalElement = InjectedElementEditor.getOriginalElement(this); if (originalElement != null) { return new FakeReference(this, originalElement.getParent()); } } return null; } @Override public PsiElement replace(@NotNull PsiElement newElement) throws IncorrectOperationException { if (InjectedElementEditor.isInEmbeddedEditor(this)) { return InjectedElementEditor.getOriginalElement(this).replace(newElement); } 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 getText(); } @Nullable public PsiElement setName(@NonNls @NotNull String newName) throws IncorrectOperationException { PsiFile fileToRename = getFileToRenameIfRenamingType(); PsiElement me = renameJustMe(newName); if (fileToRename != null) { renameMyTypesFile(newName, fileToRename); } return me; } 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 PsiElement renameJustMe(String name) { final PsiElement element = GosuPsiParseUtil.parseExpression(name, getManager()); final PsiElement child = element.getFirstChild(); replace(child); return child; } @Nullable private PsiFile getFileToRenameIfRenamingType() { final PsiElement parent = getParent(); if (parent instanceof IGosuTypeDefinition) { final PsiFile psiFile = parent.getContainingFile(); if (psiFile instanceof IGosuFile) { final String name = getName(); final VirtualFile file = psiFile.getVirtualFile(); if (file != null && name != null && name.equals(file.getNameWithoutExtension())) { return psiFile; } } } return null; } }