package com.siberika.idea.pascal.editor; import com.intellij.codeInsight.intention.LowPriorityAction; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; import com.siberika.idea.pascal.ide.actions.SectionToggle; import com.siberika.idea.pascal.lang.psi.PasEntityScope; import com.siberika.idea.pascal.lang.psi.PasFunctionDirective; import com.siberika.idea.pascal.lang.psi.PasImplDeclSection; import com.siberika.idea.pascal.lang.psi.PasModule; import com.siberika.idea.pascal.lang.psi.PasProcBodyBlock; import com.siberika.idea.pascal.lang.psi.PasTypes; import com.siberika.idea.pascal.lang.psi.PascalNamedElement; import com.siberika.idea.pascal.lang.psi.PascalStructType; import com.siberika.idea.pascal.lang.psi.impl.PasExportedRoutineImpl; import com.siberika.idea.pascal.lang.psi.impl.PasField; import com.siberika.idea.pascal.lang.psi.impl.PasRoutineImplDeclImpl; import com.siberika.idea.pascal.lang.psi.impl.PascalRoutineImpl; import com.siberika.idea.pascal.util.DocUtil; import com.siberika.idea.pascal.util.Filter; import com.siberika.idea.pascal.util.PsiUtil; import java.util.Collection; import java.util.List; /** * Author: George Bakhtadze * Date: 06/10/2013 */ public class PascalRoutineActions { public static class ActionDeclare extends PascalActionDeclare { public ActionDeclare(String name, PascalNamedElement element) { super(name, element, null); } @Override void calcData(final PsiFile file, final FixActionData data) { PasRoutineImplDeclImpl routine = (PasRoutineImplDeclImpl) data.element; String prefix = routine.getNamespace() + "."; PasProcBodyBlock block = routine.getProcBodyBlock(); int endoffs = block != null ? block.getStartOffsetInParent() : routine.getTextLength(); data.text = "\n" + routine.getText().substring(0, endoffs); if (prefix.length() > 1) { data.text = data.text.replaceFirst(prefix, ""); } data.parent = routine.getContainingScope(); data.offset = SectionToggle.findIntfPos(routine); if (data.offset < 0) { data.text = ""; } } } public static class ActionDeclareAll extends ActionDeclare implements LowPriorityAction { public ActionDeclareAll(String name, PascalNamedElement element) { super(name, element); PascalRoutineImpl routine = (PascalRoutineImpl) element; PasEntityScope scope = routine.getContainingScope(); PasModule module = PsiUtil.getElementPasModule(routine); if (null != module) { List<PascalRoutineImpl> fields = SectionToggle.collectFields(module.getPrivateFields(), PasField.FieldType.ROUTINE, null); for (PascalRoutineImpl field : fields) { if ((field != routine) && (field.getContainingScope() == scope) && (null == SectionToggle.retrieveDeclaration(field, true))) { addData(new FixActionData(field)); } } } } } public static class ActionImplement extends PascalActionDeclare { public ActionImplement(String name, PascalNamedElement element) { super(name, element, null); } @Override void calcData(final PsiFile file, final FixActionData data) { PascalRoutineImpl routine = (PascalRoutineImpl) data.element; String prefix = SectionToggle.getPrefix(routine); data.text = data.element.getText(); Collection<PasFunctionDirective> directives = PsiTreeUtil.findChildrenOfType(data.element, PasFunctionDirective.class); for (PasFunctionDirective directive : directives) { if (directive.getNode().findChildByType(PasTypes.OVERLOAD) == null) { data.text = data.text.replace(directive.getText(), ""); } } String name = data.element.getName(); data.text = "\n\n" + data.text.replaceFirst(" " + name, " " + prefix + name) + "\nbegin\n" + DocUtil.PLACEHOLDER_CARET + "\nend;\n\n"; data.offset = SectionToggle.findImplPos(routine); data.parent = routine; if (data.offset < 0) { // Suitable implementation position not found - no implementations in the class PasEntityScope classType = routine.getContainingScope(); if (classType instanceof PascalStructType) { data.text = "\n\n{ " + classType.getName() + " }" + data.text; } data.parent = PsiUtil.getModuleImplementationSection(data.element.getContainingFile()); data.parent = data.parent != null ? PsiTreeUtil.findChildOfType(data.parent, PasImplDeclSection.class) : null; if (null != data.parent) { data.offset = data.parent.getTextRange().getEndOffset(); } else { // program or library data.offset = SectionToggle.getModuleMainDeclSectionOffset(routine.getContainingFile()); if (data.offset >= 0) { data.parent = routine.getContainingFile(); } } } if (data.offset < 0) { data.text = ""; } } } public static class ActionImplementAll extends ActionImplement implements LowPriorityAction { public ActionImplementAll(String name, PascalNamedElement element) { super(name, element); PascalRoutineImpl routine = (PascalRoutineImpl) element; List<PasExportedRoutineImpl> fields = SectionToggle.collectFields(SectionToggle.getDeclFields(routine.getContainingScope()), PasField.FieldType.ROUTINE, new Filter<PasField>() { @Override public boolean allow(PasField value) { return value.getElement() instanceof PasExportedRoutineImpl; } }); for (PasExportedRoutineImpl field : fields) { if ((field != routine) && (PsiUtil.needImplementation(field)) && (null == SectionToggle.retrieveImplementation(field, true))) { addData(new FixActionData(field)); } } } } }