Skip to content

Commit

Permalink
Attempting to restore broken refactoring features
Browse files Browse the repository at this point in the history
  • Loading branch information
m0rkeulv committed Dec 9, 2023
1 parent 940cd30 commit 2f4faf1
Show file tree
Hide file tree
Showing 20 changed files with 363 additions and 148 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 1.4.21
* Improvement: Attempt at restoring `Member pull up` refactoring
* Improvement: Attempt at restoring `Member push down` refactoring
* Improvement: Attempt at restoring `extract to interface` refactoring

## 1.4.20
* Added: Allow Extract method from fields
* Bugfix: Extract method did not return value when used in var/field init expressions
Expand Down
10 changes: 5 additions & 5 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ pluginName = Haxe Toolkit Support
pluginRepositoryUrl = https://github.com/HaxeFoundation/intellij-haxe

# SemVer format -> https://semver.org
pluginVersion = 1.4.20
pluginVersion = 1.4.21

# IntelliJ Platform Properties -> https://github.com/JetBrains/gradle-intellij-plugin#intellij-platform-properties
platformType = IU
#platformType = IC

platformVersion = 2023.2.4
platformVersion = 2023.3
#platformVersion = LATEST-EAP-SNAPSHOT
platformDownloadSources = true

Expand All @@ -25,9 +25,9 @@ pluginUntilBuild = 233.*
# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
# Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22
# see flex/flash versions at : https://plugins.jetbrains.com/plugin/14508-flash-flex/versions/stable/252411
#platformPlugins = com.intellij.java, com.intellij.flex:233.11361.10, JavaScript
platformPlugins = com.intellij.java, com.intellij.flex:232.8660.142, JavaScript
#platformPlugins = com.intellij.java, com.intellij.flex:232.8660.142
platformPlugins = com.intellij.java, com.intellij.flex:233.11799.196, JavaScript
#platformPlugins = com.intellij.java, com.intellij.flex:232.8660.142, JavaScript
#platformPlugins = com.intellij.java, com.intellij.flex:233.11799.196

# Java language level used to compile sources and to generate the files for - Java 17 is required since 2022.2
javaVersion = 17
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,18 @@
package com.intellij.plugins.haxe.ide.refactoring;

import com.intellij.codeInsight.PsiEquivalenceUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.plugins.haxe.lang.lexer.HaxeTokenTypeSets;
import com.intellij.plugins.haxe.lang.psi.*;
import com.intellij.plugins.haxe.lang.psi.impl.ComponentNameScopeProcessor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiMember;
import com.intellij.psi.ResolveState;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Function;
Expand Down Expand Up @@ -80,6 +84,17 @@ public static HaxeExpression getSelectedExpression(@NotNull final Project projec
return PsiTreeUtil.getParentOfType(parent, HaxeExpression.class);
}

public static void reformat(final PsiMember movedElement) {
ApplicationManager.getApplication().runWriteAction(() -> {
Project project = movedElement.getProject();
final TextRange range = movedElement.getTextRange();
final PsiFile file = movedElement.getContainingFile();
final PsiFile baseFile = file.getViewProvider().getPsi(file.getViewProvider().getBaseLanguage());
CodeStyleManager.getInstance(project).reformatText(baseFile, range.getStartOffset(), range.getEndOffset());
});
}


@NotNull
public static List<PsiElement> getOccurrences(@NotNull final PsiElement pattern, @Nullable final PsiElement context) {
if (context == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.intellij.plugins.haxe.ide.refactoring;

import com.intellij.plugins.haxe.lang.lexer.HaxeTokenTypeSets;
import com.intellij.plugins.haxe.metadata.psi.HaxeMeta;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMember;
import com.intellij.psi.impl.source.JavaDummyHolder;
import com.intellij.psi.impl.source.tree.LazyParseablePsiElement;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MoveUpDownUtil {


public static void addMetadataAndDocs(List<PsiElement> list, PsiMember element, boolean deleteOriginal) {
Collections.reverse(list);
// insert after new member
for (PsiElement psiElement : list) {
element.getParent().addBefore(psiElement.copy(), element);
}
// remove from old member
if (deleteOriginal) {
for (PsiElement psiElement : list) {
if (psiElement.getParent() != null
&& !(psiElement.getParent() instanceof JavaDummyHolder)) {
psiElement.delete();
}
}
}
}

public static List<PsiElement> collectRelatedDocsAndMetadata(PsiMember member) {
List<PsiElement> psiElements = new ArrayList<PsiElement>();
List<PsiElement> tempList = new ArrayList<PsiElement>();
PsiElement sibling = member.getPrevSibling();
// we want to copy all relevant metadata, comments and docs when moving a member
// but we dont want to copy comments that might not belong so we only collect
// elements until we dont get any more relevant elements or we reach a different member.
while (sibling != null && !(sibling instanceof PsiMember)) {
tempList.add(sibling);
if (sibling instanceof LazyParseablePsiElement lazy) {
for (PsiElement child : lazy.getChildren()) {
if (child instanceof HaxeMeta) {
psiElements.addAll(tempList);
tempList.clear();
}
}
}
if (sibling instanceof HaxeMeta) {
psiElements.addAll(tempList);
tempList.clear();
}
if (sibling instanceof PsiComment comment && comment.getTokenType() == HaxeTokenTypeSets.DOC_COMMENT) {
psiElements.addAll(tempList);
tempList.clear();
}

sibling = sibling.getPrevSibling();
}
return psiElements;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,25 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.ComponentWithBrowseButton;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.plugins.haxe.HaxeRefactoringBundle;
import com.intellij.plugins.haxe.util.HaxeResolveUtil;
import com.intellij.psi.*;
import com.intellij.refactoring.*;
import com.intellij.refactoring.classMembers.DelegatingMemberInfoModel;
import com.intellij.refactoring.classMembers.MemberInfoBase;
import com.intellij.refactoring.extractSuperclass.ExtractSuperBaseProcessor;
import com.intellij.refactoring.extractSuperclass.JavaExtractSuperBaseDialog;
import com.intellij.refactoring.ui.MemberSelectionPanel;
import com.intellij.refactoring.ui.PackageNameReferenceEditorCombo;
import com.intellij.refactoring.util.DocCommentPolicy;
import com.intellij.refactoring.util.RefactoringMessageUtil;
import com.intellij.refactoring.util.classMembers.MemberInfo;
import com.intellij.ui.EditorComboBox;
import com.intellij.util.ArrayUtil;

import javax.swing.*;
Expand All @@ -50,6 +54,22 @@ public ExtractInterfaceDialog(Project project, PsiClass sourceClass) {
init();
}

@Override
protected ComponentWithBrowseButton<EditorComboBox> createPackageNameField() {
String packageName = HaxeResolveUtil.getPackageName(mySourceClass.getContainingFile());
PsiPackage aPackage = JavaPsiFacade.getInstance(myProject).findPackage(packageName);
return new PackageNameReferenceEditorCombo(aPackage.getQualifiedName(), myProject, "ExtractSuperBase.RECENT_KEYS",
RefactoringBundle.message("choose.destination.package"));

}

@Override
protected JTextField createExtractedSuperNameField() {
JTextField field = super.createExtractedSuperNameField();
field.setText(mySourceClass.getName()+"Interface");
return field;
}

private static List<MemberInfo> collectMembers(PsiClass c) {
return MemberInfo.extractClassMembers(c, new MemberInfoBase.Filter<PsiMember>() {
public boolean includeMember(PsiMember element) {
Expand Down Expand Up @@ -153,7 +173,7 @@ public Boolean isFixedAbstract(MemberInfo member) {
});
panel.add(memberSelectionPanel, BorderLayout.CENTER);

panel.add(myDocCommentPanel, BorderLayout.EAST);
//panel.add(myDocCommentPanel, BorderLayout.EAST);

return panel;
}
Expand All @@ -180,11 +200,15 @@ protected void setDocCommentPolicySetting(int policy) {

@Override
protected ExtractSuperBaseProcessor createProcessor() {
return new ExtractInterfaceProcessor(myProject, false, getTargetDirectory(), getExtractedSuperName(),
mySourceClass, ArrayUtil.toObjectArray(getSelectedMemberInfos(), MemberInfo.class),
return new ExtractInterfaceProcessor(myProject, false, getTargetDirectory(), getExtractedSuperName(), getTargetPackage(),
mySourceClass, ArrayUtil.toObjectArray(getSelectedMemberInfos(), MemberInfo.class),
new DocCommentPolicy(getDocCommentPolicy()));
}

public String getTargetPackage() {
return getTargetPackageName();
}

@Override
protected String getHelpId() {
return HelpID.EXTRACT_INTERFACE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,15 @@
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.plugins.haxe.ide.HaxeFileTemplateUtil;
import com.intellij.plugins.haxe.ide.refactoring.HaxeRefactoringUtil;
import com.intellij.plugins.haxe.ide.refactoring.extractSuperclass.ExtractSuperClassUtil;
import com.intellij.plugins.haxe.ide.refactoring.memberPullUp.PullUpProcessor;

import com.intellij.plugins.haxe.lang.psi.*;
import com.intellij.plugins.haxe.model.HaxeClassModel;
import com.intellij.plugins.haxe.model.HaxeDocumentModel;
import com.intellij.psi.*;
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.RefactoringActionHandler;
Expand All @@ -44,6 +50,8 @@

import javax.swing.*;

import static com.intellij.plugins.haxe.util.HaxeElementGenerator.*;

@CustomLog
public class ExtractInterfaceHandler implements RefactoringActionHandler, ElementsHandler {

Expand All @@ -56,6 +64,7 @@ public class ExtractInterfaceHandler implements RefactoringActionHandler, Elemen
private String myInterfaceName;
private MemberInfo[] mySelectedMembers;
private PsiDirectory myTargetDir;
private String packageName;
private DocCommentPolicy myJavaDocPolicy;

public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) {
Expand Down Expand Up @@ -99,6 +108,7 @@ public void run() {
myInterfaceName = dialog.getExtractedSuperName();
mySelectedMembers = ArrayUtil.toObjectArray(dialog.getSelectedMemberInfos(), MemberInfo.class);
myTargetDir = dialog.getTargetDirectory();
packageName = dialog.getTargetPackage();
myJavaDocPolicy = new DocCommentPolicy(dialog.getDocCommentPolicy());
try {
doRefactoring();
Expand All @@ -117,7 +127,7 @@ private void doRefactoring() throws IncorrectOperationException {
LocalHistoryAction a = LocalHistory.getInstance().startAction(getCommandName());
final PsiClass anInterface;
try {
anInterface = extractInterface(myTargetDir, myClass, myInterfaceName, mySelectedMembers, myJavaDocPolicy);
anInterface = extractInterface(myTargetDir, myClass, myInterfaceName, packageName, mySelectedMembers, myJavaDocPolicy);
}
finally {
a.finish();
Expand All @@ -139,23 +149,75 @@ public void run() {
static PsiClass extractInterface(PsiDirectory targetDir,
PsiClass aClass,
String interfaceName,
String packageName,
MemberInfo[] selectedMembers,
DocCommentPolicy javaDocPolicy) throws IncorrectOperationException {
aClass.getProject().getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC)
.refactoringStarted(ExtractSuperClassUtil.REFACTORING_EXTRACT_SUPER_ID, ExtractSuperClassUtil.createBeforeData(aClass, selectedMembers));
final PsiClass anInterface = JavaDirectoryService.getInstance().createInterface(targetDir, interfaceName);
//final PsiClass anInterface = JavaDirectoryService.getInstance().createInterface(targetDir, interfaceName);
HaxeClass haxeInterface = null;
try {
PsiJavaCodeReferenceElement ref = ExtractSuperClassUtil.createExtendingReference(anInterface, aClass, selectedMembers);
final PsiReferenceList referenceList = aClass.isInterface() ? aClass.getExtendsList() : aClass.getImplementsList();
assert referenceList != null;
referenceList.add(ref);
PullUpProcessor pullUpHelper = new PullUpProcessor(aClass, anInterface, selectedMembers, javaDocPolicy);
pullUpHelper.moveMembersToBase();
return anInterface;
HaxeFile newFile =
(HaxeFile)HaxeFileTemplateUtil.createClass(interfaceName, packageName, targetDir, "HaxeInterface", ExtractInterfaceHandler.class.getClassLoader());
HaxeClassModel model = newFile.getModel().getClassModel(interfaceName);
haxeInterface = model.getPsi();

if (aClass instanceof HaxeClass haxeClass) {
final PsiReferenceList referenceList = haxeClass.isInterface() ? haxeClass.getExtendsList() : haxeClass.getImplementsList();
// if the class / interface does not have extends/ implements lists we need to create these now.
if (referenceList == null) {
if (haxeClass.isInterface()) {
haxeClass.getModel().addExtends(interfaceName);
}else {
haxeClass.getModel().addImplements(interfaceName);
}
if (!packageName.trim().isEmpty() && !packageName.equalsIgnoreCase(StringUtil.getPackageName(haxeClass.getQualifiedName()))) {
HaxeFile containingFile = (HaxeFile)haxeClass.getContainingFile();
containingFile.getModel().addImport(haxeInterface.getQualifiedName());
}
}else {
referenceList.add(haxeInterface);
}
boolean move = aClass.isInterface();
if (move) {
PullUpProcessor pullUpHelper = new PullUpProcessor(aClass, haxeInterface, selectedMembers, javaDocPolicy);
pullUpHelper.moveMembersToBase();
}else {
copySignatures(haxeInterface, selectedMembers);

}
HaxeRefactoringUtil.reformat(haxeInterface);
return haxeInterface;
}
}
finally {
aClass.getProject().getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC)
.refactoringDone(ExtractSuperClassUtil.REFACTORING_EXTRACT_SUPER_ID, ExtractSuperClassUtil.createAfterData(anInterface));
catch (Exception e) {
throw new RuntimeException(e);
}
finally{
aClass.getProject().getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC)
.refactoringDone(ExtractSuperClassUtil.REFACTORING_EXTRACT_SUPER_ID, ExtractSuperClassUtil.createAfterData(haxeInterface));
}
return null;
}

private static void copySignatures(HaxeClass anInterface, MemberInfo[] members) {
HaxeDocumentModel document = anInterface.getModel().getDocument();
PsiElement rBrace = anInterface.getRBrace();
PsiElement braceParent = rBrace.getParent();

for (MemberInfo member : members) {
PsiMember psiMember = member.getMember();
if (psiMember instanceof HaxeFieldDeclaration fieldDeclaration) {
anInterface.add(fieldDeclaration);
}
if (psiMember instanceof HaxeMethodDeclaration methodDeclaration) {
HaxeMethodDeclaration workCopy = (HaxeMethodDeclaration)methodDeclaration.copy();
if(workCopy.getBody() != null)workCopy.getBody().delete();
workCopy.getMethodModifierList().forEach(PsiElement::delete);
PsiElement semi = createSemi(document.getFile().getProject());
workCopy.add(semi);
braceParent.addBefore(workCopy.copy(), rBrace);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,22 @@
* @author dsl
*/
public class ExtractInterfaceProcessor extends ExtractSuperBaseProcessor {

private String newClassPackage;
public ExtractInterfaceProcessor(Project project,
boolean replaceInstanceOf,
PsiDirectory targetDirectory,
String newClassName,
String newClassPackage,
PsiClass aClass,
MemberInfo[] memberInfos,
DocCommentPolicy javaDocPolicy) {
super(project, replaceInstanceOf, targetDirectory, newClassName, aClass, memberInfos, javaDocPolicy);
this.newClassPackage = newClassPackage;
}

protected PsiClass extractSuper(String superClassName) throws IncorrectOperationException {
return ExtractInterfaceHandler.extractInterface(myClass.getContainingFile().getContainingDirectory(), myClass, superClassName, myMemberInfos, myJavaDocPolicy);
return ExtractInterfaceHandler.extractInterface(myClass.getContainingFile().getContainingDirectory(), myClass, superClassName, newClassPackage, myMemberInfos, myJavaDocPolicy);
}

protected boolean isSuperInheritor(PsiClass aClass) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ public Boolean isFixedAbstract(MemberInfo member) {
memberInfoModel.memberInfoChanged(new MemberInfoChange<PsiMember, MemberInfo>(myMemberInfos));
memberSelectionPanel.getTable().setMemberInfoModel(memberInfoModel);
memberSelectionPanel.getTable().addMemberInfoChangeListener(memberInfoModel);

panel.add(myDocCommentPanel, BorderLayout.EAST);
//TODO support Docs rules when we have better handling for doc psi
//panel.add(myDocCommentPanel, BorderLayout.EAST);

return panel;
}
Expand Down
Loading

0 comments on commit 2f4faf1

Please sign in to comment.