Skip to content

Commit

Permalink
Merge pull request #1076 from m0rkeulv/fix/completion-hxml
Browse files Browse the repository at this point in the history
fixing IDE freeze and missing HXML completion
  • Loading branch information
m0rkeulv authored Feb 27, 2021
2 parents e6846b6 + d4855ba commit c1ee75d
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 122 deletions.
16 changes: 12 additions & 4 deletions grammar/hxml.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -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'
2 changes: 2 additions & 0 deletions src/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@
<![CDATA[
<p>Unreleased changes</p>
<ul>
<li>Add HXML completion for Haxe 4</li>
<li>Fixed issue where IDE would freeze when writing HXML files</li>
<li>Add HashLink target</li>
<li>improved block-statement parsing and added quickfix for missing semicolon</li>
<li>Add support for import.hx</li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -180,86 +181,30 @@ public static List<String> getProcessStdout(@NotNull ArrayList<String> 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<String> getProcessStderr(ArrayList<String> commandLineArguments, File dir, @Nullable HaxeSdkAdditionalDataBase haxeSdkData) {
List<String> strings = new ArrayList<String>();

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.
*
Expand All @@ -271,8 +216,4 @@ public static List<String> getProcessStdout(@NotNull ArrayList<String> commandLi
return getProcessStdout(commandLineArguments, null, haxeSdkData);
}

public static List<String> getProcessStderr(ArrayList<String> commandLineArguments, @Nullable HaxeSdkAdditionalDataBase haxeSdkData) {
return getProcessStderr(commandLineArguments, null, haxeSdkData);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -41,73 +42,118 @@
*/
public class HXMLCompilerArgumentsCompletionContributor extends CompletionContributor {

public static List<HXMLCompletionItem> COMPILER_ARGUMENTS = null;
public static List<HXMLCompletionItem> 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<HXMLCompletionItem> COMPILER_ARGUMENTS = new ArrayList<>();;
public static List<HXMLCompletionItem> 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("(-((?<short>([a-z_0-9]+)),\\s))?--(?<long>[a-z-_0-9]+)[\\s](?<param><[^>]+>)?\\s*(?<param2>\\[.*\\])?\\s+[\\t\\s]+(?<description>[^\\r\\n]+)", Pattern.CASE_INSENSITIVE);

private void getCompilerArguments() {
List<HXMLCompletionItem> compilerArguments = new ArrayList<HXMLCompletionItem>();
List<HXMLCompletionItem> compilerArguments2 = new ArrayList<HXMLCompletionItem>();
ArrayList<String> commandLine = new ArrayList<String>();
ArrayList<String> commandLine = new ArrayList<>();
List<String> strings = getStrings(commandLine);

Matcher matcher;
addHaxe4CompilerArguments(strings);
addHaxe3CompilerArguments(strings);
}

private void addHaxe3CompilerArguments(List<String> 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<String> 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<String> getStrings(ArrayList<String> commandLine) {
Module module = HaxelibCache.getHaxeModule();
commandLine.add(HaxeHelpUtil.getHaxePath(module));
commandLine.add("--help");

List<String> strings = HaxelibCommandUtils.getProcessStderr(commandLine, HaxeSdkUtilBase.getSdkData(module));
List<String> strings = HaxelibCommandUtils.getProcessStdout(commandLine, HaxeSdkUtilBase.getSdkData(module));
if (strings.size() > 0) {
strings.remove(0);
}
return strings;
}

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<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull CompletionParameters parameters,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<HXMLCompletionItem> defines = HaxeHelpCache.getInstance().getDefines();
extend(CompletionType.BASIC, PlatformPatterns.psiElement(HXMLTypes.VALUE).withParent(HXMLDefine.class),
new CompletionProvider<CompletionParameters>() {
@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<CompletionParameters> getProvider(List<HXMLCompletionItem> defines) {
return new CompletionProvider<CompletionParameters>() {
@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));
}
}
};
}
}
Loading

0 comments on commit c1ee75d

Please sign in to comment.