blob: 00068d82237d548162cdf702b8e23a07d02350f3 [file] [log] [blame]
/*
* Copyright 2000-2014 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 org.jetbrains.plugins.groovy.actions.generate;
import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.codeInsight.generation.PsiGenerationInfo;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMember;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
import org.jetbrains.plugins.groovy.refactoring.GroovyChangeContextUtil;
/**
* @author peter
*/
public class GroovyGenerationInfo<T extends PsiMember> extends PsiGenerationInfo<T> {
private static final Logger LOG = Logger.getInstance(GroovyGenerationInfo.class);
public GroovyGenerationInfo(@NotNull T member, boolean mergeIfExists) {
super(member, mergeIfExists);
}
public GroovyGenerationInfo(@NotNull T member) {
super(member);
}
@Override
public void insert(@NotNull PsiClass aClass, @Nullable PsiElement anchor, boolean before) throws IncorrectOperationException {
final T proto = getPsiMember();
if (proto instanceof GrMethod) {
GroovyChangeContextUtil.encodeContextInfo(((GrMethod)proto).getParameterList());
}
super.insert(aClass, anchor, before);
final T member = getPsiMember();
if (member == null) return;
LOG.assertTrue(member instanceof GroovyPsiElement, member);
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(member.getProject());
final PsiElement prev = member.getPrevSibling();
if (prev != null && GroovyTokenTypes.mNLS == prev.getNode().getElementType()) {
prev.replace(factory.createLineTerminator(1));
}
else if (prev instanceof PsiMember) {
member.getParent().getNode().addLeaf(GroovyTokenTypes.mNLS, "\n", member.getNode());
}
final PsiElement next = member.getNextSibling();
if (next != null && GroovyTokenTypes.mNLS == next.getNode().getElementType()) {
next.replace(factory.createLineTerminator(1));
}
else if (next instanceof PsiMember) {
member.getParent().getNode().addLeaf(GroovyTokenTypes.mNLS, "\n", next.getNode());
}
if (member instanceof GrMethod) {
GroovyChangeContextUtil.decodeContextInfo(((GrMethod)member).getParameterList(), null, null);
}
JavaCodeStyleManager.getInstance(member.getProject()).shortenClassReferences(member);
adjustDocCommentIfExists(member);
}
private static void adjustDocCommentIfExists(PsiMember member) {
final PsiElement child = member.getFirstChild();
if (child instanceof PsiDocComment) {
final Project project = member.getProject();
final GrDocComment groovyDoc = GroovyPsiElementFactory.getInstance(project).createDocCommentFromText(child.getText());
child.delete();
CodeStyleManager.getInstance(project).reformat(member);
member.getParent().addBefore(groovyDoc, member);
}
}
@Override
public PsiElement findInsertionAnchor(@NotNull PsiClass aClass, @NotNull PsiElement leaf) {
PsiElement parent = aClass instanceof GroovyScriptClass ? aClass.getContainingFile() : ((GrTypeDefinition)aClass).getBody();
if (parent == null) return null;
if (!PsiTreeUtil.isAncestor(parent, leaf, true)) {
return null; // we are not in class body
}
PsiElement element = PsiTreeUtil.findPrevParent(parent, leaf);
PsiElement lBrace = aClass.getLBrace();
if (lBrace == null) {
return null;
}
else {
PsiElement rBrace = aClass.getRBrace();
if (!GenerateMembersUtil.isChildInRange(element, lBrace.getNextSibling(), rBrace)) {
return null;
}
}
return element;
}
@Override
public void positionCaret(Editor editor, boolean toEditMethodBody) {
final T firstMember = getPsiMember();
LOG.assertTrue(firstMember.isValid());
if (toEditMethodBody) {
GrMethod method = (GrMethod)firstMember;
GrOpenBlock body = method.getBlock();
if (body != null) {
PsiElement l = body.getLBrace();
if (l != null) l = l.getNextSibling();
while (PsiImplUtil.isWhiteSpaceOrNls(l)) l = l.getNextSibling();
if (l == null) l = body;
PsiElement r = body.getRBrace();
if (r != null) r = r.getPrevSibling();
while (PsiImplUtil.isWhiteSpaceOrNls(r)) r = r.getPrevSibling();
if (r == null) r = body;
int start = l.getTextRange().getStartOffset();
int end = r.getTextRange().getEndOffset();
editor.getCaretModel().moveToOffset(Math.min(start, end));
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
if (start < end) {
//Not an empty body
editor.getSelectionModel().setSelection(start, end);
}
return;
}
}
int offset;
if (firstMember instanceof GrMethod) {
GrMethod method = (GrMethod)firstMember;
GrCodeBlock body = method.getBlock();
if (body == null) {
offset = method.getTextRange().getStartOffset();
}
else {
offset = body.getLBrace().getTextRange().getEndOffset();
}
}
else {
offset = firstMember.getTextRange().getStartOffset();
}
editor.getCaretModel().moveToOffset(offset);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
editor.getSelectionModel().removeSelection();
}
}