diff --git a/grammar/hxml.bnf b/grammar/hxml.bnf
index 157899236..a044940cc 100644
--- a/grammar/hxml.bnf
+++ b/grammar/hxml.bnf
@@ -31,8 +31,16 @@ private line_recovery ::= !(eol_)
private option_ ::= (lib | define | classpath | main | property | COMMENT)
property ::= option value? {pin=1}
-define ::= '-D' value {pin=1}
-lib ::= '-lib' value (':' value)? {pin=1}
-classpath ::= '-cp' value {pin=1}
-main ::= '-main' qualifiedName {pin=1}
+define ::= ('-D'|'--define') value {pin=1}
+lib ::= (libHx3|libHx4) value (':' value)? {pin=1}
+private libHx3 ::= '-lib'
+private libHx4 ::= '-L'|'--library'
+
+classpath ::= (classpathHx3|classpathHx4) value {pin=1}
+private classpathHx3 ::= '-cp'
+private classpathHx4 ::= '-p'
+
+main ::= (mainHx3| mainHx4) qualifiedName {pin=1}
+private mainHx3 ::= '-main'
+private mainHx4 ::= '-m'| '--main'
diff --git a/src/META-INF/plugin.xml b/src/META-INF/plugin.xml
index 0fc2a3536..22eda0a38 100644
--- a/src/META-INF/plugin.xml
+++ b/src/META-INF/plugin.xml
@@ -85,6 +85,8 @@
Unreleased changes
+ - Add HXML completion for Haxe 4
+ - Fixed issue where IDE would freeze when writing HXML files
- Add HashLink target
- improved block-statement parsing and added quickfix for missing semicolon
- Add support for import.hx
diff --git a/src/common/com/intellij/plugins/haxe/haxelib/HaxelibCommandUtils.java b/src/common/com/intellij/plugins/haxe/haxelib/HaxelibCommandUtils.java
index 3c7c301ef..da78a2058 100644
--- a/src/common/com/intellij/plugins/haxe/haxelib/HaxelibCommandUtils.java
+++ b/src/common/com/intellij/plugins/haxe/haxelib/HaxelibCommandUtils.java
@@ -39,6 +39,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
+import java.util.concurrent.TimeUnit;
/**
* Utilities to run the haxelib command and capture its output.
@@ -180,86 +181,30 @@ public static List getProcessStdout(@NotNull ArrayList commandLi
Process process = builder.start();
InputStreamReader reader = new InputStreamReader(process.getInputStream());
Scanner scanner = new Scanner(reader);
+ process.waitFor(100, TimeUnit.MILLISECONDS);
- while (scanner.hasNextLine()) {
- String nextLine = scanner.nextLine();
- strings.add(nextLine);
+ if(reader.ready()) {
+ while (scanner.hasNextLine()) {
+ String nextLine = scanner.nextLine();
+ strings.add(nextLine);
+ }
}
- process.waitFor();
- /*
- try {
- Thread.sleep(250);
- try {
- process.exitValue();
- }
- catch (IllegalThreadStateException e) {
+ if(process.isAlive()) {
+ if(!process.waitFor(10, TimeUnit.MILLISECONDS)) {
process.destroy();
}
}
- catch (InterruptedException e) {
- e.printStackTrace();
- }
- */
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- return strings;
- }
-
-
- //private static Logger log = Logger.getInstance(HaxelibCommandUtils.class);
-
- public static List getProcessStderr(ArrayList commandLineArguments, File dir, @Nullable HaxeSdkAdditionalDataBase haxeSdkData) {
- List strings = new ArrayList();
-
- try {
- ProcessBuilder builder = HaxeSdkUtilBase.createProcessBuilder(commandLineArguments, dir, haxeSdkData);
- Process process = builder.start();
- InputStreamReader reader = new InputStreamReader(process.getErrorStream());
- Scanner scanner = new Scanner(reader);
-
- while (scanner.hasNextLine()) {
- String nextLine = scanner.nextLine();
- strings.add(nextLine);
- }
- //log.error(StringUtil.join(strings, "\n"));
- process.waitFor();
- /*
- try {
- Thread.sleep(250);
- try {
- process.exitValue();
- }
- catch (IllegalThreadStateException e) {
- process.destroy();
- }
- }
- catch (InterruptedException e) {
- e.printStackTrace();
- }
- */
- }
- catch (IOException e) {
- e.printStackTrace();
- //log.error(StringUtil.getMessage(e));
}
- catch (InterruptedException e) {
+ catch (IOException | InterruptedException e) {
e.printStackTrace();
- //log.error(StringUtil.getMessage(e));
}
return strings;
}
-
/**
* Run a shell command in the (IDEA's) current directory, capturing its standard output.
*
@@ -271,8 +216,4 @@ public static List getProcessStdout(@NotNull ArrayList commandLi
return getProcessStdout(commandLineArguments, null, haxeSdkData);
}
- public static List getProcessStderr(ArrayList commandLineArguments, @Nullable HaxeSdkAdditionalDataBase haxeSdkData) {
- return getProcessStderr(commandLineArguments, null, haxeSdkData);
- }
-
}
diff --git a/src/common/com/intellij/plugins/haxe/ide/HXMLCompilerArgumentsCompletionContributor.java b/src/common/com/intellij/plugins/haxe/ide/HXMLCompilerArgumentsCompletionContributor.java
index c4786d7d6..0d027b3cc 100644
--- a/src/common/com/intellij/plugins/haxe/ide/HXMLCompilerArgumentsCompletionContributor.java
+++ b/src/common/com/intellij/plugins/haxe/ide/HXMLCompilerArgumentsCompletionContributor.java
@@ -33,6 +33,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.StringJoiner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -41,54 +42,99 @@
*/
public class HXMLCompilerArgumentsCompletionContributor extends CompletionContributor {
- public static List COMPILER_ARGUMENTS = null;
- public static List COMPILER_ARGUMENTS2 = null;
- public static final Pattern PATTERN = Pattern.compile("-([a-z-_0-9]+)[\\s](<[^>]+>)?[^:]+:[\\t\\s]+([^\\r\\n]+)");
- public static final Pattern PATTERN2 = Pattern.compile("--([a-z-_0-9]+)[^:]+:[\\t\\s]+([^\\r\\n]+)");
+ public static List COMPILER_ARGUMENTS = new ArrayList<>();;
+ public static List COMPILER_ARGUMENTS2 = new ArrayList<>();;
+ public static final Pattern HAXE3_PATTERN = Pattern.compile("-([a-z-_0-9]+)[\\s](<[^>]+>)?[^:]+:[\\t\\s]+([^\\r\\n]+)");
+ public static final Pattern HAXE3_PATTERN2 = Pattern.compile("--([a-z-_0-9]+)[^:]+:[\\t\\s]+([^\\r\\n]+)");
+
+ public static final Pattern HAXE4_PATTERN = Pattern.compile("(-((?([a-z_0-9]+)),\\s))?--(?[a-z-_0-9]+)[\\s](?<[^>]+>)?\\s*(?\\[.*\\])?\\s+[\\t\\s]+(?[^\\r\\n]+)", Pattern.CASE_INSENSITIVE);
private void getCompilerArguments() {
- List compilerArguments = new ArrayList();
- List compilerArguments2 = new ArrayList();
- ArrayList commandLine = new ArrayList();
+ ArrayList commandLine = new ArrayList<>();
List strings = getStrings(commandLine);
- Matcher matcher;
+ addHaxe4CompilerArguments(strings);
+ addHaxe3CompilerArguments(strings);
+ }
+
+ private void addHaxe3CompilerArguments(List strings) {
for (int i = 0; i < strings.size(); i++) {
String text = strings.get(i);
- matcher = PATTERN2.matcher(text);
+ Matcher matcher = HAXE3_PATTERN2.matcher(text);
if (matcher.find()) {
String group = matcher.group(1);
- if (!compilerArguments2.contains(group)) {
- compilerArguments2.add(new HXMLCompletionItem(group, matcher.group(2)));
+ if (!COMPILER_ARGUMENTS2.contains(group)) {
+ COMPILER_ARGUMENTS2.add(new HXMLCompletionItem(group, matcher.group(2)));
}
}
else
{
- matcher = PATTERN.matcher(text);
+ matcher = HAXE3_PATTERN.matcher(text);
if (matcher.find()) {
String group = matcher.group(1);
- if (!compilerArguments.contains(group)) {
+ if (!COMPILER_ARGUMENTS.contains(group)) {
String description = matcher.group(3);
String group2 = matcher.group(2);
if (group2 != null) {
group2 = group + " " + group2;
}
- compilerArguments.add(new HXMLCompletionItem(group, description, group2));
+ COMPILER_ARGUMENTS.add(new HXMLCompletionItem(group, description, group2));
}
}
}
}
- if (!compilerArguments.contains("D")) {
- compilerArguments.add(new HXMLCompletionItem("D"));
+ if (!COMPILER_ARGUMENTS.contains("D")) {
+ COMPILER_ARGUMENTS.add(new HXMLCompletionItem("D"));
}
+ }
+ private void addHaxe4CompilerArguments(List strings) {
+ for (int i = 0; i < strings.size(); i++) {
+ String text = strings.get(i);
+
+ Matcher matcher = HAXE4_PATTERN.matcher(text);
- COMPILER_ARGUMENTS = compilerArguments;
- COMPILER_ARGUMENTS2 = compilerArguments2;
+ if (matcher.find()) {
+ String shortCmd = getTextFromGroup(matcher, "short");
+ String longCmd = getTextFromGroup(matcher, "long");
+
+ if (shortCmd != null && !COMPILER_ARGUMENTS.contains(shortCmd)) {
+ String description = getTextFromGroup(matcher, "description");
+ StringJoiner presentation = new StringJoiner(" ");
+ String params = getTextFromGroup(matcher, "params");
+ String params2 = getTextFromGroup(matcher, "params2");
+ presentation.add(shortCmd);
+ if (params != null) presentation.add(params);
+ if (params2 != null) presentation.add(params2);
+ COMPILER_ARGUMENTS.add(new HXMLCompletionItem(shortCmd, description, presentation.toString()));
+ }
+
+ if (longCmd != null && !COMPILER_ARGUMENTS2.contains(longCmd)) {
+ String description = getTextFromGroup(matcher, "description");
+ StringJoiner presentation = new StringJoiner(" ");
+ String params = getTextFromGroup(matcher, "params");
+ String params2 = getTextFromGroup(matcher, "params2");
+ presentation.add(longCmd);
+ if (params != null) presentation.add(params);
+ if (params2 != null) presentation.add(params2);
+
+ COMPILER_ARGUMENTS2.add(new HXMLCompletionItem(longCmd, description, presentation.toString()));
+ }
+ }
+ }
+ }
+
+ private String getTextFromGroup(Matcher matcher, String groupName) {
+ try {
+ return matcher.group(groupName);
+ }catch (IllegalArgumentException e) {
+ // group not found
+ return null;
+ }
}
private List getStrings(ArrayList commandLine) {
@@ -96,7 +142,7 @@ private List getStrings(ArrayList commandLine) {
commandLine.add(HaxeHelpUtil.getHaxePath(module));
commandLine.add("--help");
- List strings = HaxelibCommandUtils.getProcessStderr(commandLine, HaxeSdkUtilBase.getSdkData(module));
+ List strings = HaxelibCommandUtils.getProcessStdout(commandLine, HaxeSdkUtilBase.getSdkData(module));
if (strings.size() > 0) {
strings.remove(0);
}
@@ -104,10 +150,10 @@ private List getStrings(ArrayList commandLine) {
}
public HXMLCompilerArgumentsCompletionContributor() {
- if (COMPILER_ARGUMENTS == null) {
+ if (COMPILER_ARGUMENTS.isEmpty()) {
getCompilerArguments();
}
- extend(CompletionType.BASIC, PlatformPatterns.psiElement(HXMLTypes.OPTION).withLanguage(HXMLLanguage.INSTANCE),
+ extend(CompletionType.BASIC, PlatformPatterns.psiElement(HXMLTypes.KEY_TOKEN).withLanguage(HXMLLanguage.INSTANCE),
new CompletionProvider() {
@Override
protected void addCompletions(@NotNull CompletionParameters parameters,
diff --git a/src/common/com/intellij/plugins/haxe/ide/HXMLDefineCompletionContributor.java b/src/common/com/intellij/plugins/haxe/ide/HXMLDefineCompletionContributor.java
index 1b838091e..508161dbe 100644
--- a/src/common/com/intellij/plugins/haxe/ide/HXMLDefineCompletionContributor.java
+++ b/src/common/com/intellij/plugins/haxe/ide/HXMLDefineCompletionContributor.java
@@ -22,29 +22,40 @@
import com.intellij.patterns.PlatformPatterns;
import com.intellij.plugins.haxe.hxml.psi.HXMLDefine;
import com.intellij.plugins.haxe.hxml.psi.HXMLTypes;
+import com.intellij.plugins.haxe.hxml.psi.HXMLValue;
import com.intellij.plugins.haxe.util.HaxeHelpCache;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import java.util.List;
+import static com.intellij.patterns.PlatformPatterns.psiElement;
+
/**
* Created by as3boyan on 19.11.14.
*/
public class HXMLDefineCompletionContributor extends CompletionContributor {
public HXMLDefineCompletionContributor() {
final List defines = HaxeHelpCache.getInstance().getDefines();
- extend(CompletionType.BASIC, PlatformPatterns.psiElement(HXMLTypes.VALUE).withParent(HXMLDefine.class),
- new CompletionProvider() {
- @Override
- protected void addCompletions(@NotNull CompletionParameters parameters,
- ProcessingContext context,
- @NotNull CompletionResultSet result) {
- for (int i = 0; i < defines.size(); i++) {
- HXMLCompletionItem completionItem = defines.get(i);
- result.addElement(LookupElementBuilder.create(completionItem.name).withTailText(" " + completionItem.description, true));
- }
- }
- });
+
+ // intelliJ 2018 and older
+ extend(CompletionType.BASIC, PlatformPatterns.psiElement(HXMLTypes.VALUE).withParent(HXMLDefine.class), getProvider(defines));
+ // intelliJ 2019 and newer
+ extend(CompletionType.BASIC, PlatformPatterns.psiElement().withParent(HXMLValue.class).withSuperParent(2, HXMLDefine.class), getProvider(defines));
+ }
+
+ @NotNull
+ private CompletionProvider getProvider(List defines) {
+ return new CompletionProvider() {
+ @Override
+ protected void addCompletions(@NotNull CompletionParameters parameters,
+ ProcessingContext context,
+ @NotNull CompletionResultSet result) {
+ for (int i = 0; i < defines.size(); i++) {
+ HXMLCompletionItem completionItem = defines.get(i);
+ result.addElement(LookupElementBuilder.create(completionItem.name).withTailText(" " + completionItem.description, true));
+ }
+ }
+ };
}
}
diff --git a/src/common/com/intellij/plugins/haxe/ide/HXMLHaxelibCompletionContributor.java b/src/common/com/intellij/plugins/haxe/ide/HXMLHaxelibCompletionContributor.java
index 9740278fc..afa1386f1 100644
--- a/src/common/com/intellij/plugins/haxe/ide/HXMLHaxelibCompletionContributor.java
+++ b/src/common/com/intellij/plugins/haxe/ide/HXMLHaxelibCompletionContributor.java
@@ -20,10 +20,13 @@
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.patterns.PlatformPatterns;
import com.intellij.plugins.haxe.haxelib.HaxelibCache;
import com.intellij.plugins.haxe.hxml.HXMLLanguage;
import com.intellij.plugins.haxe.hxml.psi.HXMLLib;
+import com.intellij.plugins.haxe.hxml.psi.HXMLTokenType;
import com.intellij.plugins.haxe.hxml.psi.HXMLTypes;
+import com.intellij.plugins.haxe.hxml.psi.HXMLValue;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
@@ -46,22 +49,29 @@ public HXMLHaxelibCompletionContributor() {
availableHaxelibs = haxelibCache.getAvailableHaxelibs();
localHaxelibs = haxelibCache.getLocalHaxelibs();
- extend(CompletionType.BASIC, psiElement(HXMLTypes.VALUE).withParent(HXMLLib.class).withLanguage(HXMLLanguage.INSTANCE),
- new CompletionProvider() {
- @Override
- protected void addCompletions(@NotNull CompletionParameters parameters,
- ProcessingContext context,
- @NotNull CompletionResultSet result) {
- for (int i = 0; i < availableHaxelibs.size(); i++) {
- result.addElement(LookupElementBuilder.create(availableHaxelibs.get(i))
- .withTailText(" available at haxelib", true));
- }
+ // intelliJ 2018 and older
+ extend(CompletionType.BASIC, psiElement(HXMLTypes.VALUE).withParent(HXMLLib.class).withLanguage(HXMLLanguage.INSTANCE), getProvider());
+ // intelliJ 2019 and newer
+ extend(CompletionType.BASIC, PlatformPatterns.psiElement().withParent(HXMLValue.class).withSuperParent(2, HXMLLib.class).withLanguage(HXMLLanguage.INSTANCE), getProvider());
+ }
+
+ @NotNull
+ private CompletionProvider getProvider() {
+ return new CompletionProvider() {
+ @Override
+ protected void addCompletions(@NotNull CompletionParameters parameters,
+ ProcessingContext context,
+ @NotNull CompletionResultSet result) {
+ for (int i = 0; i < availableHaxelibs.size(); i++) {
+ result.addElement(LookupElementBuilder.create(availableHaxelibs.get(i))
+ .withTailText(" available at haxelib", true));
+ }
- for (int i = 0; i < localHaxelibs.size(); i++) {
- result.addElement(LookupElementBuilder.create(localHaxelibs.get(i))
- .withTailText(" installed", true));
- }
- }
- });
+ for (int i = 0; i < localHaxelibs.size(); i++) {
+ result.addElement(LookupElementBuilder.create(localHaxelibs.get(i))
+ .withTailText(" installed", true));
+ }
+ }
+ };
}
}