/* * Copyright 2000-2013 JetBrains s.r.o. * Copyright 2014-2014 AS3Boyan * Copyright 2014-2014 Elias Ku * * 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 com.intellij.plugins.haxe.ide.generation; import com.intellij.codeInsight.FileModificationService; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.plugins.haxe.ide.HaxeNamedElementNode; import com.intellij.plugins.haxe.lang.psi.*; import com.intellij.plugins.haxe.util.HaxeElementGenerator; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiParserFacade; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; /** * @author: Fedor.Korotkov */ abstract public class BaseCreateMethodsFix<T extends HaxeNamedComponent> { private final Set<T> elementsToProcess = new LinkedHashSet<T>(); protected final HaxeClass myHaxeClass; protected final HaxeGenericSpecialization specializations; protected PsiElement anchor = null; public BaseCreateMethodsFix(final HaxeClass haxeClass) { myHaxeClass = haxeClass; specializations = HaxeClassResolveResult.create(haxeClass).getSpecialization(); } protected void evalAnchor(@Nullable Editor editor, PsiFile file) { if (editor == null) return; final int caretOffset = editor.getCaretModel().getOffset(); if (myHaxeClass instanceof HaxeClassDeclaration) { final HaxeClassBody body = ((HaxeClassDeclaration)myHaxeClass).getClassBody(); assert body != null; for (PsiElement child : body.getChildren()) { if (child.getTextOffset() > caretOffset) return; anchor = child; } return; } anchor = file.findElementAt(caretOffset); } /** * must be called not in write action */ public void beforeInvoke(@NotNull final Project project, final Editor editor, final PsiFile file) { } public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException { if (!FileModificationService.getInstance().prepareFileForWrite(file)) return; evalAnchor(editor, file); processElements(project, getElementsToProcess()); } protected void processElements(Project project, Set<T> elementsToProcess) { for (T e : elementsToProcess) { anchor = doAddMethodsForOne(project, buildFunctionsText(e), anchor); modifyElement(e); } } protected void modifyElement(T element) { } protected abstract String buildFunctionsText(T e); public PsiElement doAddMethodsForOne(final Project project, final String functionsText, PsiElement anchor) throws IncorrectOperationException { if (functionsText != null && functionsText.length() > 0) { List<HaxeNamedComponent> elements = HaxeElementGenerator.createNamedSubComponentsFromText(project, functionsText); final PsiElement insert = myHaxeClass instanceof HaxeClassDeclaration ? ((HaxeClassDeclaration)myHaxeClass).getClassBody() : myHaxeClass; assert insert != null; for (PsiElement element : elements) { if (element instanceof HaxeVarDeclarationPart) { element = element.getParent(); } anchor = insert.addAfter(element, anchor); anchor = afterAddHandler(element, anchor); } } return anchor; } protected PsiElement afterAddHandler(PsiElement element, PsiElement anchor) { final PsiElement newLineNode = PsiParserFacade.SERVICE.getInstance(element.getProject()).createWhiteSpaceFromText("\n\n"); anchor.getParent().addBefore(newLineNode, anchor); return anchor; } public void addElementToProcess(final T function) { elementsToProcess.add(function); } public void addElementsToProcessFrom(@Nullable final Collection<HaxeNamedElementNode> selectedElements) { if (selectedElements == null) { return; } for (HaxeNamedElementNode el : selectedElements) { addElementToProcess((T)el.getPsiElement()); } } public Set<T> getElementsToProcess() { final T[] objects = (T[])elementsToProcess.toArray(new HaxeNamedComponent[elementsToProcess.size()]); final Comparator<T> tComparator = new Comparator<T>() { public int compare(final T o1, final T o2) { return o1.getTextOffset() - o2.getTextOffset(); } }; final int size = elementsToProcess.size(); final LinkedHashSet<T> result = new LinkedHashSet<T>(size); final List<T> objectsFromSameFile = new ArrayList<T>(); PsiFile containingFile = null; for (int i = 0; i < size; ++i) { final T object = objects[i]; final PsiFile currentContainingFile = object.getContainingFile(); if (currentContainingFile != containingFile) { if (containingFile != null) { Collections.sort(objectsFromSameFile, tComparator); result.addAll(objectsFromSameFile); objectsFromSameFile.clear(); } containingFile = currentContainingFile; } objectsFromSameFile.add(object); } Collections.sort(objectsFromSameFile, tComparator); result.addAll(objectsFromSameFile); elementsToProcess.clear(); elementsToProcess.addAll(result); return elementsToProcess; } }