Skip to content

Commit

Permalink
key-value introduce variable + Suggest enum values
Browse files Browse the repository at this point in the history
  • Loading branch information
m0rkeulv committed Jan 21, 2024
1 parent 7ee74e7 commit 01edea2
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 1.4.23
* Fixed: introduce variable feature for introduce key-value intention
* Added: Suggest enum values for case completion in switch blocks.

## 1.4.22
* Added: Auto-detect preprocessing definitions from build config (enabled by default)
> This feature can be disabled under `Settings -> Build, Execution, Deployment -> Haxe`. If disabled only manually configured definitions will be used.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,26 @@

import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.util.TextRange;
import com.intellij.patterns.PsiElementPattern;
import com.intellij.patterns.StandardPatterns;
import com.intellij.plugins.haxe.HaxeLanguage;
import com.intellij.plugins.haxe.lang.lexer.HaxeTokenTypeSets;
import com.intellij.plugins.haxe.lang.psi.*;
import com.intellij.plugins.haxe.model.HaxeEnumValueModel;
import com.intellij.plugins.haxe.model.HaxeMemberModel;
import com.intellij.plugins.haxe.model.type.HaxeExpressionEvaluator;
import com.intellij.plugins.haxe.model.type.ResultHolder;
import com.intellij.plugins.haxe.model.type.SpecificHaxeClassReference;
import com.intellij.plugins.haxe.model.type.SpecificTypeReference;
import com.intellij.plugins.haxe.util.HaxeElementGenerator;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.TreeUtil;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ProcessingContext;
import icons.HaxeIcons;
import org.jetbrains.annotations.NotNull;

import java.util.*;
Expand All @@ -43,6 +52,7 @@
import static com.intellij.plugins.haxe.ide.completion.KeywordCompletionData.keywordWithSpace;
import static com.intellij.plugins.haxe.lang.lexer.HaxeTokenTypeSets.*;
import static com.intellij.plugins.haxe.lang.lexer.HaxeTokenTypes.*;
import static java.util.function.Predicate.not;

/**
* @author: Fedor.Korotkov
Expand All @@ -55,6 +65,8 @@ public class HaxeKeywordCompletionContributor extends CompletionContributor {
}
}
};
private static final PsiElementPattern.Capture<PsiElement> afterCaseKeyword =
psiElement().afterSiblingSkipping(skippableWhitespace, psiElement().withText("case"));

public HaxeKeywordCompletionContributor() {

Expand Down Expand Up @@ -137,6 +149,7 @@ private static void suggestKeywords(PsiElement position, @NotNull CompletionResu

if (insideSwitchCase.accepts(completionElementAsComment)) {
addKeywords(lookupElements, SWITCH_BODY_KEYWORDS);
addEnumValuesIfSourceIsEnum(completionElementAsComment, lookupElements);
}

if (isAfterIfStatement.accepts(completionElementAsComment)) {
Expand Down Expand Up @@ -172,6 +185,41 @@ private static void suggestKeywords(PsiElement position, @NotNull CompletionResu
result.addAllElements(lookupElements);
}

private static void addEnumValuesIfSourceIsEnum(PsiElement completionElementAsComment, List<LookupElement> lookupElements) {
boolean isAfterCase = afterCaseKeyword.accepts(completionElementAsComment);
HaxeSwitchStatement parent = PsiTreeUtil.getParentOfType(completionElementAsComment, HaxeSwitchStatement.class);
if (parent == null) return;

HaxeExpression expression = parent.getExpression();
if (expression == null) return;

ResultHolder holder = HaxeExpressionEvaluator.evaluate(expression, null).result;
if (!holder.isEnum()) return;

SpecificTypeReference type = holder.getType();
if (type instanceof SpecificHaxeClassReference classReference) {
List<HaxeSwitchCase> list = parent.getSwitchBlock().getSwitchCaseList();
List<String> alreadyInUse =
list.stream().map(HaxeSwitchCase::getSwitchCaseExprList).filter(not(List::isEmpty)).map(exprs -> exprs.get(0).getText())
.toList();
List<HaxeMemberModel> members = classReference.getHaxeClassModel().getMembers(null);
for (HaxeMemberModel member : members) {

if (member instanceof HaxeEnumValueModel model) {
String name = member.getName();
if (alreadyInUse.contains(name)) continue;
String completionText = (isAfterCase ? "" : "case ") + name + " ";

LookupElementBuilder element = LookupElementBuilder.create(model, completionText)
.withIcon(HaxeIcons.Enum)
.withItemTextItalic(true);

LookupElement element1 = PrioritizedLookupElement.withPriority(element, 10000);
lookupElements.add(element1);
}
}
}
}


private static HaxeFile createCopyWithFakeIdentifierAsComment(PsiElement position, List<String> keywordsFromParser) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.intellij.plugins.haxe.ide.intention;

import com.intellij.codeInsight.CodeInsightUtilCore;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.plugins.haxe.HaxeBundle;
import com.intellij.plugins.haxe.HaxeLanguage;
import com.intellij.plugins.haxe.lang.psi.HaxePsiCompositeElement;
import com.intellij.plugins.haxe.lang.psi.HaxeReference;
import com.intellij.plugins.haxe.ide.refactoring.introduce.HaxeIntroduceHandler;
import com.intellij.plugins.haxe.lang.psi.*;
import com.intellij.plugins.haxe.model.type.HaxeExpressionEvaluator;
import com.intellij.plugins.haxe.model.type.ResultHolder;
import com.intellij.plugins.haxe.model.type.SpecificHaxeClassReference;
Expand All @@ -20,6 +22,10 @@
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;

public class KeyValueIteratorForLoopIntention extends BaseIntentionAction {

private SpecificHaxeClassReference resolvedType;
Expand Down Expand Up @@ -52,8 +58,33 @@ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file

@Override
public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PsiElement itr = HaxeElementGenerator.createForInLoop(project, "key", "value", haxeReference.getText());
haxeReference.replace(itr);
HaxeForStatement forLoop = HaxeElementGenerator.createForInLoop(project, "key", "value", haxeReference.getText());
forLoop = (HaxeForStatement)haxeReference.replace(forLoop.copy());

if (!editor.isViewer()) {
CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(forLoop);
HaxeKeyValueIterator keyValueIterator = forLoop.getKeyValueIterator();

introduceKeyValueIterators(editor, keyValueIterator);
}
}




private static void introduceKeyValueIterators(Editor editor, HaxeKeyValueIterator keyValueIterator) {
HaxeIteratorkey keyItr = keyValueIterator.getIteratorkey();
HaxeIteratorValue valueItr = keyValueIterator.getIteratorValue();

HaxeComponentName keyNamed = keyItr.getComponentName();
HaxeComponentName valueNamed = valueItr.getComponentName();

final var introducer = new HaxeIntroduceHandler.HaxeInplaceVariableIntroducer(keyNamed, editor, List.of(), Map.of( valueNamed, "value"));
introducer.setElementToRename(keyNamed);
TextRange range = keyNamed.getTextRange();
editor.getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset());
editor.getCaretModel().moveToOffset(range.getEndOffset());
introducer.performInplaceRefactoring(new LinkedHashSet<>(List.of()));
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@
package com.intellij.plugins.haxe.ide.refactoring.introduce;

import com.intellij.codeInsight.CodeInsightUtilCore;
import com.intellij.codeInsight.template.TemplateBuilderImpl;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.CaretModel;
Expand Down Expand Up @@ -594,6 +594,7 @@ protected abstract PsiElement addDeclaration(@NotNull final PsiElement expressio

public static class HaxeInplaceVariableIntroducer extends InplaceVariableIntroducer<PsiElement> {
private final HaxeComponentName myTarget;
private Map<HaxeComponentName, String> additional;

public HaxeInplaceVariableIntroducer(HaxeComponentName target,
HaxeIntroduceOperation operation,
Expand All @@ -609,6 +610,23 @@ public HaxeInplaceVariableIntroducer(HaxeComponentName target,
occurrences.toArray(new PsiElement[0]), null);
myTarget = target;
}
public HaxeInplaceVariableIntroducer(HaxeComponentName target,
Editor editor,
List<PsiElement> occurrences, Map<HaxeComponentName, String> additional) {
super(target, editor, editor.getProject(), "Introduce Variable",
occurrences.toArray(new PsiElement[0]), null);
this.additional = additional;
myTarget = target;
}

@Override
protected void addAdditionalVariables(TemplateBuilderImpl builder) {
if (additional != null) {
for (Map.Entry<HaxeComponentName, String> entry : additional.entrySet()) {
builder.replaceElement(entry.getKey(), entry.getValue());
}
}
}

@Override
protected PsiElement checkLocalScope() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,9 @@ public static HaxeForStatement createForInLoop(Project myProject, String varName
return (HaxeForStatement) createStatementFromText(myProject, forAinBLoop);

}
public static PsiElement createForInLoop(Project myProject, String key, String value, String source) {
public static HaxeForStatement createForInLoop(Project myProject, String key, String value, String source) {
String forAinBLoop = "for("+key+" => "+value+" in "+source+") {\n\n}";
PsiElement text = createStatementFromText(myProject, forAinBLoop);
HaxeForStatement text = (HaxeForStatement)createStatementFromText(myProject, forAinBLoop);
return text;

}
Expand Down

0 comments on commit 01edea2

Please sign in to comment.