Skip to content

Commit

Permalink
Autodetect definitions, add definitions in completion suggestions, nu…
Browse files Browse the repository at this point in the history
…ll checks and index out of bounds guard.
  • Loading branch information
m0rkeulv committed Jan 14, 2024
1 parent e3e2d44 commit 7f1ae00
Show file tree
Hide file tree
Showing 27 changed files with 829 additions and 142 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Changelog

## 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.
> Auto-detected definitions can be overridden with user defined definitions or removed by setting definition value = `*UNSET*`
* Added: Completion suggestions for preprocessor definitions
* Added: Support for resolving & completion for typeParameters with anonymous structures.
* Added: Check argument types in call expressions for functionTypes from typeParameters.
* Improvement: better handling of import statements with aliases.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.util.List;


/**
Expand All @@ -32,18 +33,18 @@ public enum HaxeTarget {

// Target clFlag Extension, OutputDir, OutputType Description

NEKO( "neko", ".n", "neko", OUTPUT_TYPE.FILE, HaxeCommonBundle.message("haxe.target.neko")),
JAVA_SCRIPT( "js", ".js", "js", OUTPUT_TYPE.FILE, HaxeCommonBundle.message("haxe.target.js")),
FLASH( "swf", ".swf", "flash", OUTPUT_TYPE.FILE, HaxeCommonBundle.message("haxe.target.swf")),
CPP( "cpp", ".exe", "cpp", OUTPUT_TYPE.DIRECTORY, HaxeCommonBundle.message("haxe.target.cpp")),
CPPIA( "cppia", ".cppia", "cppia", OUTPUT_TYPE.FILE, HaxeCommonBundle.message("haxe.target.cppia")),
PHP( "php", ".php", "php", OUTPUT_TYPE.DIRECTORY, HaxeCommonBundle.message("haxe.target.php")),
JAVA( "java", ".jar", "java", OUTPUT_TYPE.DIRECTORY, HaxeCommonBundle.message("haxe.target.java")),
CSHARP( "cs", ".exe", "cs", OUTPUT_TYPE.DIRECTORY, HaxeCommonBundle.message("haxe.target.csharp")),
PYTHON( "python", ".py", "python", OUTPUT_TYPE.FILE, HaxeCommonBundle.message("haxe.target.python")),
LUA( "lua", ".lua", "lua", OUTPUT_TYPE.FILE, HaxeCommonBundle.message("haxe.target.lua")),
HL( "hl", ".hl", "hl", OUTPUT_TYPE.FILE, HaxeCommonBundle.message("haxe.target.hl")),
INTERP( "-interp","", "", OUTPUT_TYPE.NONE, HaxeCommonBundle.message("haxe.target.interp"));
NEKO( "neko", ".n", "neko", OUTPUT_TYPE.FILE, HaxeCommonBundle.message("haxe.target.neko"), List.of("neko", "sys")),
JAVA_SCRIPT( "js", ".js", "js", OUTPUT_TYPE.FILE, HaxeCommonBundle.message("haxe.target.js"), List.of("js")),
FLASH( "swf", ".swf", "flash", OUTPUT_TYPE.FILE, HaxeCommonBundle.message("haxe.target.swf"), List.of("flash")),
CPP( "cpp", ".exe", "cpp", OUTPUT_TYPE.DIRECTORY, HaxeCommonBundle.message("haxe.target.cpp"), List.of("cpp", "sys")),
CPPIA( "cppia", ".cppia", "cppia", OUTPUT_TYPE.FILE, HaxeCommonBundle.message("haxe.target.cppia"), List.of("cppia")),
PHP( "php", ".php", "php", OUTPUT_TYPE.DIRECTORY, HaxeCommonBundle.message("haxe.target.php"), List.of("php", "sys")),
JAVA( "java", ".jar", "java", OUTPUT_TYPE.DIRECTORY, HaxeCommonBundle.message("haxe.target.java"), List.of("java", "jvm", "sys")),
CSHARP( "cs", ".exe", "cs", OUTPUT_TYPE.DIRECTORY, HaxeCommonBundle.message("haxe.target.csharp"), List.of("cs", "sys")),
PYTHON( "python", ".py", "python", OUTPUT_TYPE.FILE, HaxeCommonBundle.message("haxe.target.python"), List.of("python")),
LUA( "lua", ".lua", "lua", OUTPUT_TYPE.FILE, HaxeCommonBundle.message("haxe.target.lua"), List.of("lua")),
HL( "hl", ".hl", "hl", OUTPUT_TYPE.FILE, HaxeCommonBundle.message("haxe.target.hl"), List.of("hl")),
INTERP( "-interp","", "", OUTPUT_TYPE.NONE, HaxeCommonBundle.message("haxe.target.interp"), List.of("eval"));

private enum OUTPUT_TYPE {
FILE,
Expand All @@ -57,12 +58,15 @@ private enum OUTPUT_TYPE {
private final String fileExtension;
private final OUTPUT_TYPE outputType;

HaxeTarget(String flag, String fileExtension, String outputDir, OUTPUT_TYPE outputType, String description) {
private final List<String> definitions;

HaxeTarget(String flag, String fileExtension, String outputDir, OUTPUT_TYPE outputType, String description, List<String> definitions) {
this.flag = flag;
this.description = description;
this.outputDir = outputDir;
this.outputType = outputType;
this.fileExtension = fileExtension;
this.definitions = definitions;
}

public String getFlag() {
Expand All @@ -73,6 +77,10 @@ public String getCompilerFlag() {
return "-" + flag;
}

public List<String> getDefinitions() {
return definitions;
}

public String getDefaultOutputSubdirectory() {
return outputDir;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@
import com.intellij.plugins.haxe.util.HaxeTrackedModifiable;
import com.intellij.util.containers.ContainerUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.*;

/**
* @author: Fedor.Korotkov
Expand All @@ -43,7 +42,9 @@
public class HaxeProjectSettings implements PersistentStateComponent<Element>, HaxeTrackedModifiable {
public static final String HAXE_SETTINGS = "HaxeProjectSettings";
public static final String DEFINES = "defines";
public static final String AUTO_DETECT = "auto_detect_defines";
private String userCompilerDefinitions = "";
private boolean autoDetectDefinitions = true;
private HaxeModificationTracker tracker = new HaxeModificationTracker(getClass().getName());

public Set<String> getUserCompilerDefinitionsAsSet() {
Expand All @@ -59,6 +60,26 @@ public String[] getUserCompilerDefinitions() {
return userCompilerDefinitions.split(",");
}

@NotNull
public Map<String, String> getUserCompilerDefinitionMap() {
Map<String, String> defintionMap = new HashMap<>();
String[] definitions = getUserCompilerDefinitions();
for (String def : definitions) {
if (def.trim().isEmpty()) continue;

String[] split = def.split("=", 2);

// Dashes are subtraction operators, so definitions (on the command line) that
// contain dashes are mapped to an equivalent using underscores (when looking up definitions).
String key = split[0];
String value = split.length > 1 ? split[1] : null;
defintionMap.put(key, value == null ? "" : value);


}
return defintionMap;
}

public void setUserCompilerDefinitions(String[] userCompilerDefinitions) {
this.userCompilerDefinitions = StringUtil.join(ContainerUtil.filter(userCompilerDefinitions, new Condition<String>() {
@Override
Expand All @@ -72,13 +93,21 @@ public boolean value(String s) {
@Override
public void loadState(Element state) {
userCompilerDefinitions = state.getAttributeValue(DEFINES, "");
String value = state.getAttributeValue(AUTO_DETECT);
if (value == null) {
// using default value "true" value if not found
autoDetectDefinitions = true;
}else {
autoDetectDefinitions = Boolean.parseBoolean(value);
}
tracker.notifyUpdated();
}

@Override
public Element getState() {
final Element element = new Element(HAXE_SETTINGS);
element.setAttribute(DEFINES, userCompilerDefinitions);
element.setAttribute(AUTO_DETECT, String.valueOf(autoDetectDefinitions));
return element;
}

Expand All @@ -91,4 +120,12 @@ public Stamp getStamp() {
public boolean isModifiedSince(Stamp s) {
return tracker.isModifiedSince(s);
}

public boolean getAutoDetectDefinitions() {
return autoDetectDefinitions;
}

public void setAutoDetectDefinitions(boolean selected) {
autoDetectDefinitions = selected;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.plugins.haxe.config.ui.HaxeProjectSettingsForm">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
Expand All @@ -10,10 +10,19 @@
<children>
<component id="9d265" class="com.intellij.plugins.haxe.config.ui.HaxeProjectSettingsForm$MyAddDeleteListPanel" binding="myAddDeleteListPanel" custom-create="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="8e063" class="javax.swing.JCheckBox" binding="autoDetectDefinitionsFromCheckBox">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Automatically detect definitions from build configurations"/>
<toolTipText value="Whether to use the Haxe compiler to help with variable and method name suggestions."/>
</properties>
</component>
</children>
</grid>
</form>
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
public class HaxeProjectSettingsForm {
private JPanel myPanel;
private MyAddDeleteListPanel myAddDeleteListPanel;
private JCheckBox autoDetectDefinitionsFromCheckBox;

public JComponent getPanel() {
return myPanel;
Expand All @@ -41,15 +42,22 @@ public JComponent getPanel() {
public boolean isModified(HaxeProjectSettings settings) {
final List<String> oldList = Arrays.asList(settings.getUserCompilerDefinitions());
final List<String> newList = Arrays.asList(myAddDeleteListPanel.getItems());
final boolean isEqual = oldList.size() == newList.size() && new HashSet<>(oldList).containsAll(newList);
return !isEqual;
final boolean listEqual = oldList.size() == newList.size() && new HashSet<>(oldList).containsAll(newList);

final boolean autoDetectOld = settings.getAutoDetectDefinitions();
final boolean autoDetectNew = autoDetectDefinitionsFromCheckBox.isSelected();
boolean checkboxChanged = autoDetectOld != autoDetectNew;

return !listEqual || checkboxChanged;
}

public void applyEditorTo(HaxeProjectSettings settings) {
settings.setUserCompilerDefinitions(myAddDeleteListPanel.getItems());
settings.setAutoDetectDefinitions(autoDetectDefinitionsFromCheckBox.isSelected());
}

public void resetEditorFrom(HaxeProjectSettings settings) {
autoDetectDefinitionsFromCheckBox.setSelected(settings.getAutoDetectDefinitions());
myAddDeleteListPanel.removeALlItems();
for (String item : settings.getUserCompilerDefinitions()) {
myAddDeleteListPanel.addItem(item);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.startup.ProjectActivity;
import com.intellij.plugins.haxe.haxelib.definitions.HaxeDefineDetectionManager;
import kotlin.Unit;
import kotlin.coroutines.Continuation;
import lombok.CustomLog;
Expand Down Expand Up @@ -70,6 +71,7 @@ public void modulesAdded(@NotNull Project project, @NotNull List<? extends Modul
@Override
public void moduleRemoved(@NotNull Project project, @NotNull Module module) {
HaxelibCacheManager.removeInstance(module);
HaxeDefineDetectionManager.getInstance(project).removeDetectedDefinitions(module);
HaxelibProjectUpdater.getInstance().findProjectTracker(project).moduleRemoved(module);
ExternalSystemProjectTracker.getInstance(project).scheduleProjectRefresh();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,11 @@
import com.intellij.plugins.haxe.buildsystem.nmml.NMMLFileType;
import com.intellij.plugins.haxe.config.HaxeConfiguration;
import com.intellij.plugins.haxe.config.sdk.HaxeSdkType;
import com.intellij.plugins.haxe.haxelib.definitions.HaxeDefineDetectionManager;
import com.intellij.plugins.haxe.ide.module.HaxeModuleSettings;
import com.intellij.plugins.haxe.ide.module.HaxeModuleType;
import com.intellij.plugins.haxe.ide.projectStructure.autoimport.HaxelibAutoImport;
import com.intellij.plugins.haxe.util.HaxeDebugTimeLog;
import com.intellij.plugins.haxe.util.HaxeDebugUtil;
import com.intellij.plugins.haxe.util.HaxeFileUtil;
import com.intellij.plugins.haxe.util.Lambda;
import com.intellij.plugins.haxe.util.*;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.xml.XmlFile;
Expand Down Expand Up @@ -124,10 +122,8 @@ static HaxelibProjectUpdater getInstance() {
*/
public void openProject(@NotNull Project project) {
ProjectTracker tracker = myProjects.add(project);
if(tracker!= null) {
tracker.setDirty(true);
myQueue.add(tracker);
}
tracker.setDirty(true);
myQueue.add(tracker);
}

/**
Expand Down Expand Up @@ -765,7 +761,17 @@ public void synchronizeClasspaths(@NotNull ProjectTracker tracker) {
ProgressManager progressManager = ProgressManager.getInstance();
progressManager.executeProcessUnderProgress(()-> syncProjectClasspath(tracker, true), progressManager.getProgressIndicator());
progressManager.executeProcessUnderProgress(()-> syncModuleClasspaths(tracker, true), progressManager.getProgressIndicator());
recalculateDefinitions(tracker);
}

private void recalculateDefinitions(ProjectTracker tracker) {

Project project = tracker.myProject;
HaxeDefineDetectionManager.getInstance(project).recalculateDefinitions(project);

// TODO create index for PP keywords and use index for reparse list of files
// consider FileIndexingFlavorProvider<Flavor> or other ways to limit hte amount of files needing reparse
HaxeUtil.reparseProjectFiles(tracker.getProject(), false);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@ public static HaxelibSemVer create(@Nullable String semver) {
Integer.parseInt(matcher.group(2)),
Integer.parseInt(matcher.group(3)));

}
@Nullable
public static HaxelibSemVer create(float f) {
String[] split = String.valueOf(f).split("\\.");
int major = Integer.parseInt(split[0]);
int minor = split.length > 1 ? Integer.parseInt(split[1]) : 0;
int patch = 0;
return new HaxelibSemVer(major, minor, patch);

}

/**
Expand Down
Loading

0 comments on commit 7f1ae00

Please sign in to comment.